Methods

Spatial data preparation

Load data

Maps data

We use three different shapefiles for the continental U.S. land mass, the State waters of maine, new hampshire, massachusets, connecticut, rhode island, new york, new jersey, delaware, maryland, virginia, north carolina and the North East EEZ. Moreover, we use the NOAA dataset of landings per port.

1.- Land shapefile

Covers the US land territory for visualization. Data provided from the map package.


States <- c("maine", "new hampshire", "massachusetts", "connecticut", "rhode island", "new york", "new jersey", "delaware", "maryland", "virginia", "north carolina") 

# -------------- #
# US State Map (land)
# -------------- #

land_sf <- st_as_sf(map("state", plot = FALSE, fill = TRUE)) %>% 
  filter(ID %in% States) %>% 
  mutate(abrev = c("CT","DE","ME","MD","MA","NH","NJ","NY","NC","RI","VA"),
         state = str_to_sentence(ID)
         )

# Visual exploration (o.k! )
ggplot(land_sf) +
  geom_sf(aes(fill = state)) +
  scale_fill_manual(values = state_pallet) +
  theme_dark()

NA
NA
2.- EEZ shapefile

Used the Sea Around Us shapefle updated to June 2016.

# Load it!
eez_sf <- st_read(path_world) %>%
  rename(eez_name = Name) %>%
  st_transform(crs = 4326) %>% # 4326
  filter(eez_name == "USA (East Coast)") %>%
  st_simplify(preserveTopology = TRUE, dTolerance = 0.1) #0.1 for paper
Reading layer `SAUEEZ_July2015' from data source 
  `/Volumes/Enterprise/Data/Spatial/SAU/SAU_Shapefile/SAUEEZ_July2015.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 280 features and 7 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -180 ymin: -63.66443 xmax: 180 ymax: 87.02394
Geodetic CRS:  WGS 84
Warning in st_simplify.sfc(st_geometry(x), preserveTopology, dTolerance) :
  st_simplify does not correctly simplify longitude/latitude data, dTolerance needs to be in decimal degrees
# Load it!
eez_sf <- st_read(path_world) %>%
  rename(eez_name = Name) %>%
  st_transform(crs = 4326) %>% # 4326
  filter(eez_name == "USA (East Coast)") %>%
  st_simplify(preserveTopology = TRUE, dTolerance = 0.1) #0.1 for paper
Reading layer `SAUEEZ_July2015' from data source 
  `/Volumes/Enterprise/Data/Spatial/SAU/SAU_Shapefile/SAUEEZ_July2015.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 280 features and 7 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: -180 ymin: -63.66443 xmax: 180 ymax: 87.02394
Geodetic CRS:  WGS 84
Warning in st_simplify.sfc(st_geometry(x), preserveTopology, dTolerance) :
  st_simplify does not correctly simplify longitude/latitude data, dTolerance needs to be in decimal degrees
# Visual exploration (o.k! )
ggplot(eez_sf) +
  geom_sf() +
  theme_dark()

3.- State waters

Covers the state waters of the NE US states. Data from data.gov.

License: No license information was provided. If this work was prepared by an officer or employee of the United States government as part of that person’s official duties it is considered a U.S. Government Work.

4.- Fishing ports

We used Global Fishing Watch’s database on Anchorages, Ports and Voyages.

The Global Fishing Watch anchorages dataset is a global database of anchorage locations where vessels congregate. The dataset contains over 160,000 individual anchorage locations, which are further grouped into nearly 32,000 ports when applicable.

So…Looks like some ports are “far from shore” which I don’t really know what it means. For now, I am only selecting those ports that ar 0 meter from shore.

There are still too many ports in each state (?). Specially New Jersey! One approach is to use NOAA’s landing-per-port data to filter out…

4.1 NOAA’s data

This dataset includes all landings from 2015-July 2021. It includes the species landed, the port, and the Hull ID and vessel name for black sea bass and summer flounder.

License, from Sarah Smith: This is confidential data, so please do not share this file with others. You may need to contact NOAA directly just to request permission. My contact has been Alison Ferguson () in their data department.

This approach removes a lot of ports to the point that Delaware is completely port-less

4.2 World Port Index

In this approach we only use the ports categorized within the WPI and with distance_from_shore_m == 0 and at_dock == TRUE.

  • at_dock == Anchorages within a 450 meter buffer around a combined land shape file are considered at dock.

This approach might be better suited. It also has teh advantage that we are using the WPI.

This is how all the shapefiles look like together

Create base shapefile for computation

As a first step we need to divide the NE US EEZ among the different states. For that, we expanded a buffer-polygon to the 200 nautical miles to then estimate the percentage that each expanded polygon occupied. For the initial buffer point we used two approaches; state waters and US ports. Note that in all cases these areas overlapped and percentages accounted for it. We did this by following these steps:

    1. Expand state waters / US ports using a buffer
    1. Grid that buffer on a 0.3 resolution
    1. Crop the buffer to the EEZ

1. Expand Spatial regions (a.k.a buffers)

1.1 State Waters

We set a buffer of 410000 m (410 km, ~ 221 nm) that overshoots the EEZ a bit, but is eventually cropped

1.1 US. Ports

We set a buffer of 5 deg (510 km, ~ 221 nm) that overshoots the EEZ a bit, but is eventually cropped

2. Expand grid within buffer

Here we expand a grid within the buffer so we can estimate the proportion of each state.

Note: Dark grey shaded area is the grid and is the same for both approaches

2.1 Merge grid and buffers

Once we have a gridded area, we converted the grid to a sf so we can merge it with the buffered states and ports and finally filter out everything outside the states polygon

2.1.1 State Waters

2.1.1 Fishing Ports

3. Crop buffers to EEZ

Finally, we crop the grided buffers to within the EEZ to capture the actual water space.

Note: This step takes quite a while because of the size of the EEZ shapefile. No, you cannot use st_simplify() here

3.1 State Waters

3.2 Fishing Ports

3.3 Differences at croped level

By looking at the plots we do not see that the number of grid cells that each state has is slightly different depending on the approach. This comes to light when we count the number of gridcells that each state gets in each approach. We see that the state waters one is substantially higher.

We can visualize the difference of the cropped area for each state next. Again, the fishing port approach results in less area for all states, but such area is not proportional among states. For example, Delaware looses roughly 35% of fishing grounds with this approach

grid_eez_sw_df %>% 
  mutate(approach = "state_waters") %>% 
  bind_rows(grid_eez_fp_df) %>%
  mutate(approach = ifelse(is.na(approach),"fishing_port",approach)) %>% 
  group_by(state,approach) %>% 
  summarise(n_grid = n()) %>% 
  spread(approach,n_grid) %>% 
  mutate(difference =state_waters-fishing_port,
         percentage_sw = round((difference/state_waters)*100)
         )
`summarise()` has grouped output by 'state'. You can override using the `.groups` argument.

And here is the map visualization of the cropped difference

3.4 Paper plot; Buffer plot

#### Data needed ####

# Get state order from North to south
state_order <- my_path("R","Partial/", name = "grid_eez_fp_df.csv",read = T) %>%
  group_by(state) %>% 
  summarise(
    order = mean(lat)
  ) %>% 
  mutate(abrev = c("CT","DE","ME","MD","MA","NH","NJ","NY","NC","RI","VA")
  ) %>% 
  arrange(desc(order)) %>% 
  mutate(order= c("b","a",letters[3:11])) # weirdly maine goes below



# Load grid of state waters
grid_eez_sw_sf <- st_read(my_path("D","Spatial/grid_eez_sw_sf", name = "grid_eez_sf.shp")) %>% 
  select(index,state,geometry) %>% 
  mutate(method = "state_waters",
         state = str_to_sentence(state)) %>% 
  left_join(state_order)

grid_eez_sw_sf$group <- factor(grid_eez_sw_sf$abrev,      # Reordering group factor levels
                               levels = state_order$abrev)


# Load grid of fishing ports
grid_eez_fp_sf <- st_read(my_path("D","Spatial/grid_eez_fp_sf", name = "grid_eez_fp.shp")) %>% 
  select(index,state = jursdct,geometry) %>% 
  mutate(method = "fishing_port",
         state = str_to_sentence(state))%>% 
  left_join(state_order)


grid_eez_fp_sf$group <- factor(grid_eez_fp_sf$abrev,      # Reordering group factor levels
                               levels = state_order$abrev)


# Plotting 
# Make sure st_simplify() is run for eez sf

# State waters plot

p_sw <- gridExtra::grid.arrange(
  # Overall (overlapping) position
  ggplot(grid_eez_sw_sf) +
    geom_sf(data = eez_sf, aes(), fill = "white") + 
    geom_sf(aes(color =abrev , fill = abrev), alpha = 0.3) +
    geom_sf(data = land_sf, aes()) +
    ggsflabel::geom_sf_label_repel(data = land_sf, aes(label= abrev), 
                                   size = 4,
                                   box.padding = 0.10,
                                   hjust = 1) +
    scale_color_manual(values = state_pallet) +
    scale_fill_manual(values = state_pallet) +
    my_ggtheme_p(leg_pos = "",
                 ax_tx_s = 13) +
    coord_sf(ylim = c(30,48)) +
    scale_y_continuous(breaks = c(30,35,40,45))+
    labs(x = "", y = "", title = "A) State waters extrapolation") +
    theme(plot.title = element_text(size = 20)),
  # Showing each state separately
  ggplot(grid_eez_sw_sf) +
    geom_sf(data = land_sf, aes(), fill = "grey80") +
    geom_sf(aes(color = abrev),size = 0.1, alpha = 0.3) +
    facet_wrap(~ group) +
    theme(legend.position = "top") +
    scale_color_manual(values = state_pallet,
                       # labels = unique(grid_eez_sw_sf$group)) +
                       labels = grid_eez_sw_sf %>% arrange(order) %>%  pull(state) %>% unique()) +
    ggtitle("") +
    my_ggtheme_p(leg_pos = "",
                 ax_tx_s = 11,
                 axx_tx_ang = 45,
                 hjust = 1
    ),
  nrow = 1)


##### ------------- ####
# Fishing Ports plot
##### ------------- ####

p_fp <- gridExtra::grid.arrange(
  # Overall (overlapping) position
  ggplot(grid_eez_fp_sf) +
    geom_sf(data = eez_sf, aes(), fill = "white") + 
    geom_sf(aes(color = abrev, fill = abrev), alpha = 0.3) +
    geom_sf(data = land_sf, aes()) +
    ggsflabel::geom_sf_label_repel(data = land_sf, aes(label= abrev), 
                                   size = 4,
                                   box.padding = 0.10,
                                   hjust = 1) +
    scale_color_manual(values = state_pallet) +
    scale_fill_manual(values = state_pallet) +
    my_ggtheme_p(leg_pos = "",
                 ax_tx_s = 13) +
    coord_sf(ylim = c(30,48)) +
    scale_y_continuous(breaks = c(30,35,40,45)) +
    labs(x = "", y = "", title = "B) Fishing ports extrapolation") +
    theme(plot.title = element_text(size = 20)),
  # Showing each state separately
  ggplot(grid_eez_fp_sf) +
    geom_sf(data = land_sf, aes(), fill = "grey80") +
    geom_sf(aes(color = abrev),size = 0.1, alpha = 0.3) +
    facet_wrap(~ group) +
    theme(legend.position = "top") +
    scale_color_manual(values = state_pallet,
                       # labels = unique(grid_eez_fp_sf$group)) +
                       labels = grid_eez_fp_sf %>% arrange(order) %>%  pull(state) %>% unique()) +
    ggtitle("") +
    my_ggtheme_p(leg_pos = "",
                 ax_tx_s = 11,
                 axx_tx_ang = 45,
                 hjust = 1
    ),
  nrow = 1)



combined_plot <- gridExtra::grid.arrange(p_sw,p_fp,
                                         bottom = "Longitude",
                                         left = "Latitude")

ggsave(filename = "buffer_figure_b.jpg",
       plot = combined_plot,
       path = my_path("R","Figures"),
       width = 11,
       height = 11
)

Buffer figure for paper

Interpolation rutine

In this step we interpolate the survey data within the previously created grid following a Triangular Irregular Surface method.

  • We removed cases where wtcpue < 0

Functions needed

We need to create a couple of functions to run the whole process

Interpolation main fx (tis).

This is the main function used to interpolate the data per year. It follows a Triangular Irregular Surface method using the interp::interp() function. If you want to see the function clic on code


tis <- function(input_data, grid, yr, taxa, reg){
  
  # --------------- #
  # Testing
  # print(paste(yr))
  # yr = 1976
  # --------------- #
  
  # Filter data
  data <- input_data %>% 
    filter(year == yr,
           spp == taxa,
           region == reg
    ) %>% 
    # Average duplicated hauls in the same spot
    group_by(region,year,spp,lat,lon) %>%
    summarise_at(vars(wtcpue),
                 mean,na.rm = T)
    
  # Only interpolate cases where there is more than 3 rows
  # Marked by the function 
    if(nrow(data) <= 3){
      fit_tin <- tibble()
    }else{
      
      # Triangular Irregular Surface
      fit_tin <- interp::interp( # using {interp}
        x = data$lon,           # the function actually accepts coordinate vectors
        y = data$lat,
        z = data$wtcpue,
        xo = grid$lon,     # here we already define the target grid
        yo = grid$lat,
        output = "points"
      ) %>% 
        bind_cols() %>% 
        bind_cols(grid) %>%
        mutate(year = yr,
               region = reg,
               spp = taxa) %>% 
        select(index, state, year, region, spp, lon=x, lat=y, value = z)
      
    }
   
    return(fit_tin)
}

# Test me
# Needs variables in Control panel
# Test no data: "Alosa aestivalis", reg = "Northeast US Fall", yr = 1974 
# tis(input_data = ocean_data, grid = grid_eez_df, taxa = "Illex illecebrosus", reg = "Northeast US Fall", yr = 1973)



# lapply(years,tis,input_data = ocean_data, grid = grid_eez_df, taxa = "Illex illecebrosus", reg = regions[2])
Run function

This is a sub-function that runs the tis() function by taxa and region. It saves the output as a .csv file for each species.



run_tis <- function(input_data, grid, years, taxa, reg, method){
  
  
  # Run tis for species and surveys
  for(r in 1:2){
    
    partial_df <- bind_rows(
      lapply(years,tis,input_data = input_data, grid = grid, taxa = taxa, reg = reg[r])
    )
    
    if(r == 1){
      historic_tif <- partial_df
    }else{
      historic_tif <- bind_rows(historic_tif,partial_df)
    }
    
  }
  
  # ----------------------- #
  # Save dataset per species
  # ----------------------- #
  
  # Set file name
  name <- paste0("tif_",str_replace(taxa," ","_"),".csv")
  
  complement <- paste0("Partial/Interpolation/",method)
  
  # Set path name
  save_path <- my_path("R",complement)
  
  # Set complete path
  save_name <- paste0(save_path,name)
  
  # Create folder if it does not exist
  if(file.exists(save_path) == F){
    dir.create(save_path)
  }
  
  #  Save file
  write_csv(historic_tif,save_name)
  
  return_msg <- paste("Interpolation done for", taxa)
  
  return(return_msg)
  
  
}

# Test me
    # run_tis(input_data = ocean_data, grid = grid_eez_fp_df, taxa = "Centropristis striata", years = seq(1970,1980), reg = regions, method = "testa")

Survey data

The interpolation was done with NOAA Northeast Fisheries Science Center Spring and Fall Bottom Trawl Surveys data provided by Ocean adapt. Data was accessed trough the Github.

In primary publications using data from the database, please cite Pinsky et al. 2013. Marine taxa track local climate velocities. Science 341: 1239-1242 doi: 10.1126/science.1239352, as well as the original data sources.

  • Using only the Northeast US Fall and Spring bottom trawl survey data for now
Splitting up data
  • No part on spatial analysis. Can be ignored.

This is just a sub-step to split up the data into single species files. This makes the app faster as it only needs to load species specific data, rather than all the data at de beginning.

Control Pannel

This is where we load the required data and prepare to run the interpolation function. Note that some of the data here has been previously created

# Missing runs
spp <- tibble(taxa=spp) %>% 
  anti_join(spp_runs) %>% 
  pull(taxa)
Joining, by = "taxa"

Run routine

Here we just run the routine for each of the species present in the Northeast US Fall and Spring surveys between 1973 and 2019.

  • Note there are 43 identified taxa
  • Some taxa do not have presence data in some years
# Run them all in parallel
mclapply(spp,
       run_tis, 
       input_data = ocean_data,
       grid = grid_eez_fp_df,
       years = years,
       reg = regions,
       method = "fp"
)
Error in mclapply(spp, run_tis, input_data = ocean_data, grid = grid_eez_fp_df,  : 
  could not find function "mclapply"

Results

Results are now for eight species managed under Mid-Atlantic Council Management Plans according to NOAA.

Scomber scombrus, Peprilus triacanthus (butterfish), Illex illecebrosus (shortfin squid), Paralichthys dentatus (summer flounder), Stenotomus chrysops (Scoop), Centropristis striata (black sea bass), Pomatomus saltatrix (Bluefish), Lopholatilus chamaeleonticeps (Golden tilefish), Caulolatilus microps (blueline tilefish) and Clupea harengus

state_lat <- historic_spp %>%
  group_by(state) %>% 
  summarise(
    order = mean(lat)
  ) %>% 
  mutate(abrev = c("CT","DE","ME","MD","MA","NH","NJ","NY","NC","RI","VA")
  ) %>% 
  arrange(desc(order)) %>% 
  mutate(order= letters[1:11])
Error in group_by(., state) : object 'historic_spp' not found

Average proportion

This map shows the aggregated extrapolated value from all three species per State average across the whole study period within each State’s water.

Note: This is intended to be a supplemental figure


 data_grid <- historic_spp %>% 
  group_by(state,lat,lon,region) %>% 
  summarise(sum = sum(value,na.rm= T), .groups = "drop") %>% # sum of all species
  group_by(state,lat,lon,region) %>% 
  summarise(mean = mean(sum,na.rm= T), .groups = "drop") # average of all years


ggplot(data = subset(data_grid, !is.na(mean))) +
  geom_tile(
    aes(
      x = lon,
      y = lat,
      fill = mean,
      col = mean
    )
  ) +
  geom_sf(data = land_sf, aes()) +
  facet_wrap(~ state  +  region,
             ncol = 4) +
  labs(x = "Longitude", y = "Latitude") +
  scale_fill_viridis("Mean Interpolation", alpha = 0.8) +
  scale_color_viridis("Mean Interpolation", alpha = 0.8) +
  theme_bw()

Proportion Change

Here we show the average proportion of the interpolation by State and time period. Time periods were arbitrary defined as;

  • Early; 1973 to 1984
  • Mid; 1985 to 1997
  • Late; 1998 to 2011
  • Now; 2012 to 2019

Notes: Figure represents the Spring survey. This computation considers the Overlapping of state waters.

Dynamic figure: Aggregated Proportional change per survey


total_fited <- historic_spp %>% 
  group_by(year,region) %>% 
  summarise(total_value = sum(value,na.rm=T),.groups = "drop")


state_fit <- historic_spp %>% 
  group_by(state,year,region) %>% 
  summarise(state_value = sum(value,na.rm= T), .groups = "drop") %>% 
  left_join(total_fited,
            by = c("year","region")) %>%
  mutate(percentage = state_value/total_value*100) %>% 
  left_join(periods,
            by = "year") %>% 
  group_by(state,order,label,region) %>% 
  summarise(mean_per = round(mean(percentage)),.groups = "drop")

# check percentages
# state_fit %>% 
#   group_by(period) %>% 
#   summarise(sum(mean_per))


p <- land_sf %>% 
  left_join(state_fit,
            by = "state") %>% 
  ggplot() +
  # geom_sf(aes(fill = mean_per)) +
  geom_sf(aes(fill = mean_per, text = paste(state, mean_per,"% of proportion"))) +
  viridis::scale_fill_viridis("Average proportion per State", alpha = 0.8) +
  facet_wrap(~ region + label, 
             nrow = 2) +
  labs(x = "Latitude", 
       y = "Longitude") +
  my_ggtheme_p(facet_tx_s = 12,
               leg_pos = "bottom") +
  theme(legend.key.width = unit(1,"line")) +
  theme_dark()

ggplotly(p,
         tooltip = "text",
         dynamicTicks = FALSE) %>% 
    style(hoverlabel = list(bgcolor = "white"), hoveron = "fill")

Paper figure; Per species maps

total_fited <- historic_spp %>% 
  group_by(year,region,spp) %>% 
  summarise(total_value = sum(value,na.rm=T),.groups = "drop")


state_fit <- historic_spp %>% 
  group_by(state,year,region,spp) %>% 
  summarise(state_value = sum(value,na.rm= T), .groups = "drop") %>% 
  left_join(total_fited,
            by = c("year","region","spp")) %>%
  mutate(percentage = state_value/total_value*100) %>% 
  left_join(periods,
            by = "year") %>% 
  group_by(state,order,label,region,spp) %>% 
  summarise(mean_per = round(mean(percentage)),.groups = "drop") %>% 
  #Only show results for spring
  filter(str_detect(region,"Spring")) %>% 
  mutate(spp = gsub(" ","\n",spp))

# The plot
map_plot <- land_sf %>% 
  left_join(state_fit,
            by = "state") %>% 
  ggplot() +
  geom_sf(aes(fill = mean_per)) +
  viridis::scale_fill_viridis("Average proportion per State", alpha = 0.8) +
  facet_grid(spp ~ label) +
  labs(x = "Longitude", 
       y = "Latitude") +
  my_ggtheme_p(facet_tx_s = 20,
               leg_pos = "bottom",
               axx_tx_ang = 45,
               ax_tx_s = 12,
               ax_tl_s = 18,
               hjust = 1) +
  theme(legend.key.width = unit(4,"line")) 


  ggsave(filename = "proportion_chg_spp.jpg",
         plot = map_plot,
         path = my_path("R","Figures"),
         width = 14,
         height = 14
         )

Proportion change per species map for paper

Paper figure: Aggregated Proportional change


total_fited <- historic_spp %>% 
  group_by(year,region) %>% 
  summarise(total_value = sum(value,na.rm=T),.groups = "drop")


state_fit <- historic_spp %>% 
  group_by(state,year,region) %>% 
  summarise(state_value = sum(value,na.rm= T), .groups = "drop") %>% 
  left_join(total_fited,
            by = c("year","region")) %>%
  mutate(percentage = state_value/total_value*100) %>% 
  left_join(periods,
            by = "year") %>% 
  group_by(state,order,label,region) %>% 
  summarise(mean_per = round(mean(percentage)),.groups = "drop") %>% 
  filter(str_detect(region,"Spring"))


agg_map <- land_sf %>% 
  left_join(state_fit,
            by = "state") %>% 
  ggplot() +
  geom_sf(aes(fill = mean_per)) +
  viridis::scale_fill_viridis("Average proportion per State", alpha = 0.8) +
  facet_wrap(~ label, nrow = 1) +
  labs(x = "Longitude", 
       y = "Latitude") +
  my_ggtheme_p(facet_tx_s = 16,
               leg_pos = "bottom",
               leg_tl_s = 14,
               ax_tx_s = 10,
               ax_tl_s = 14) +
  theme(legend.key.width = unit(2,"line")) 

  ggsave(filename = "proportion_chg_agg.jpg",
         plot = agg_map,
         path = my_path("R","Figures"),
         width = 9,
         height = 5
         )

Proportion change aggregated all species map for paper

Area plot

This graph shows the proportion of the interpolation value each State has over time.

Note: This plot is interactive. For ease comparison between States you can;

  • One click on any State to remove it from the plot
  • Two clicks on any State to isolate it from the plot (other states can then be added by just clicking on them).
  • The bottom panel allows you to reduce the time frame

Dynamic aggregated plot


total_fited <- historic_spp %>% 
  group_by(year,region) %>% 
  summarise(total_value = sum(value,na.rm=T),.groups = "drop")

# group by state
state_fit <- historic_spp %>% 
  group_by(state,year,region) %>% 
  summarise(state_value = sum(value,na.rm= T), .groups = "drop") %>% 
  left_join(total_fited,
            by = c("year","region")) %>%
  mutate(percentage = state_value/total_value*100)

# Plot me
p <- ggplot(state_fit) +
  geom_area(
    aes(
      x = year,
      y = round(percentage),
      fill = state
    )
  ) +
  ylab("Percentage (%)") +
  # viridis::scale_fill_viridis(discrete = T, alpha = 0.8) +
  scale_fill_manual(values = state_pallet) +
  MyFunctions::my_ggtheme_p() +
  facet_wrap(~region, ncol = 1) +
  theme_dark()

ggplotly(p,
         dynamicTicks = TRUE) %>% 
  layout(hovermode = "x") %>%
  rangeslider()

Area plot (running mean)

This graph shows the proportion of each State smoothed over a *10 years running mean**. It allows to better see increasing and decreasing trends.

Dynamic aggregated plot

Note: This plot is also interactive and thus, follows the same options of the previous one.


# group by state
state_fit <- historic_spp %>% 
  group_by(state,year,region,.groups = "drop") %>% 
  summarise(state_value = sum(value,na.rm= T), .groups = "drop") %>% 
  left_join(total_fited,
            by = c("year","region")) %>%
  mutate(percentage = state_value/total_value*100) %>% 
  group_by(state,region) %>% 
  mutate(RMean = zoo::rollmean(x = percentage, 
                            10,
                            fill = NA,
                            na.rm=T)
    ) %>%  
  left_join(state_lat)

# Plot me
p <- ggplot(state_fit) +
  geom_area(
    aes(
      x = year,
      y = round(RMean),
      fill = state
      # fill = order
    )
  ) +
  ylab("10 yrs running average (%)") +
  scale_fill_manual(
    "State",
    values = state_pallet,
    # labels = state_fit %>% arrange(order) %>%  pull(state) %>% unique()
  ) +
  MyFunctions::my_ggtheme_p() +
  facet_wrap(~region, ncol = 1) +
  theme_dark()

suppressWarnings(
ggplotly(p,
         dynamicTicks = TRUE) %>% 
  layout(hovermode = "x") %>% 
  # add_trace() %>% 
  rangeslider()
)

Paper figure: Aggregated Proportional change

Proportion change aggregated all species map for paper

Paper figure: Per Species Proportional change

Proportion change aggregated all species map for paper

Historic quota Vs distributions

This section of the results explores the differences between the historic distribution of te stock and the historic quota allocation. We collected the proportion of the total quota that each State gets for each species.

Right now the analysis only covers black sea bass, summer flounder and scup. But we can go speceis by species to see which ones have their quota allocated by state to include them in the analysis.

Note: We are using the new allocations based on the stock’s most recent biomass distribution*

For State-level managed species see the Atlantic States Marine Fisheries Comission website and go species-by-species.


quota_allocation <- state_lat %>% 
  mutate(
    "Centropristis striata" = c(
      0.0040, #ME
      0.0040, #NH
      0.1564, #MA
      0.1323, #RI
      0.0367, #CT
      0.0857, #NY
      0.2010, #NJ
      0.0411, #DE
      0.0888, #MD
      0.1614, #VA
      0.0888 #NC
    ),
    "Paralichthys dentatus" = c(
      0.0004756, #ME 
      0.0000046, #NH 
      0.0682046, #MA 
      0.1568298, #RI 
      0.0225708, #CT 
      0.0764699, #NY 
      0.1672499, #NJ 
      0.0001779, #DE 
      0.0203910, #MD
      0.2131676, #VA
      0.2744584 #NC
    ),
    "Stenotomus chrysops" = c(
      0.0012101, #ME
      0.0000000, #HN
      0.2158729, #MA
      0.5619456, #RI
      0.0315399, #CT
      0.1582466, #NY
      0.0291667, #NJ
      0.0000000, #DE
      0.0001190, #MD
      0.0016502, #VA
      0.0002490 #NC
    )
  ) %>% 
  gather("spp","quota",4:6)

# Double check they all add to 1...
quota_allocation %>% 
  group_by(spp) %>% 
  summarise_at(vars(quota),sum)


quota_allocation %>% 
  arrange(order) %>% 
  select(-order) %>% 
  spread(spp,quota) %>% 
  kable()

Get data ready


total_fited <- historic_spp %>% 
  group_by(year,region,spp) %>% 
  summarise(total_value = sum(value,na.rm=T),.groups = "drop")

# group by state
state_fit <- historic_spp %>% 
  group_by(state,year,region,spp) %>% 
  summarise(state_value = sum(value,na.rm= T), .groups = "drop") %>% 
  left_join(total_fited,
            by = c("year","region","spp")) %>%
  mutate(percentage = state_value/total_value*100) %>% 
  #Only show results for spring
  filter(str_detect(region,"Spring"))

quota_df <- quota_allocation %>% 
  left_join(historic_spp) %>% 
  group_by(state,abrev,year,region,spp,quota) %>% 
  summarise(state_value = sum(value,na.rm= T), .groups = "drop") %>% 
  left_join(total_fited,
            by = c("year","region","spp")) %>%
  mutate(Distribution = state_value/total_value*100,
         Historic = quota*100) %>% 
  group_by(state,quota,spp) %>% 
  mutate(RMean = zoo::rollmean(x = Distribution, 
                            10,
                            fill = NA,
                            na.rm=T)
    ) %>% 
  #Only show results for spring
  filter(str_detect(region,"Spring"),
         !is.na(RMean) # Remove NAs from rollmean
         ) %>%  
  left_join(state_lat) %>% 
  filter(
    # spp =="Centropristis striata"
    spp %in% quota_allocation$spp
  )

head(quota_df) %>% 
  kable()

Exploring different ways to show the results

Difference line plot

This version shows the difference between the Historic quota allocation and the distribution proportion of the stock:

  • diff < 0 = the distribution proportion is larger than the allocated quota
  • diff > 0 = the distribution proportion is smaller than the allocated quota
# Option one

quota_df %>%
  mutate(diff = Historic- Distribution,
         diff_rmean = RMean- Distribution) %>% 
  gather("type","value",diff:diff_rmean) %>% 
  # View()
  ggplot() +
  geom_line(
    aes(
      x = year,
      y = value,
      color = order
    )
  ) +
  scale_color_manual("State",
    values = state_pallet,
    labels = quota_df %>% arrange(order) %>%  pull(state) %>% unique()
    ) +
  facet_grid(type~spp, 
             scales = "free") +
  theme_dark()

Linetype plot

Here, we plot the distributional quota (solid lines) with each State’s allocation with dashed (—-) lines

# Option one

quota_df %>% 
  gather("level","quota",Distribution:RMean) %>% 
  # mutate(diff = quota_per- percentage) %>% 
  # View()
  ggplot() +
  geom_line(
    aes(
      x = year,
      y = quota,
      color = order
    )
  ) +
  labs(x = "Year",y = "Quota (%)") +
  scale_fill_manual("State",
    values = state_pallet,
    labels = quota_df %>% arrange(order) %>%  pull(state) %>% unique()
    ) +
  scale_color_manual("State",
    values = state_pallet,
    labels = quota_df %>% arrange(order) %>%  pull(state) %>% unique()
    ) +
  scale_linetype("Quota") +
  facet_grid(spp ~ level)+
  theme_dark()

Efficiency index

The idea here is create and efficiency index (Danger!) that computes the alignment between the distribution and the actual allocation. The index is simply;

\[ei = \frac{HistoricQuota}{DistributionProportion}\] So, in cases where ei = 1, the quota is aligned with the distribution; when ei > 1 then the historic quota is more than the stock’s State’s distribution, contrarily, ei < 1 means that the historic quota is less than what the State currently has.

Note: - There are some crazzy outliers that have been removed, for now… - Bottom plot representing index as a Rmean

As a normal year to year
# Option one

eff_index <- quota_df %>% 
  # filter(
  #   spp =="Centropristis striata"
  # ) %>% 
  mutate(index = Distribution/Historic,
         index_rmean = RMean/Historic) %>%
  gather("level","index",index:index_rmean) %>%
  filter(index < 5) # there are some craaaazy outliers
  # View()
  
ggplot(eff_index) +
  geom_line(
    aes(
      x = year,
      y = index,
      color = state
    ),
  ) +
  labs(x = "Year",y = "Efficiency index") +
  scale_fill_manual("State",
    values = state_pallet,
    labels = quota_df %>% arrange(order) %>%  pull(state) %>% unique()
    ) +
  scale_color_manual("State",
    values = state_pallet,
    labels = quota_df %>% arrange(order) %>%  pull(state) %>% unique()
    ) +
  facet_grid(level~spp,
             scales = "free")+
  theme_dark()
LS0tCnRpdGxlOiAiU3BhdGlhbCBBbmFseXNpcyIKYXV0aG9yOiAiSnVsaWFubyBQYWxhY2lvcyBBYnJhbnRlcyIKb3V0cHV0OgogICMgaHRtbF9kb2N1bWVudDoKICBodG1sX25vdGVib29rOgogICAgZmlnX3dpZHRoOiA2CiAgICBmaWdfaGVpZ2h0OiA0CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDYKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiBmYWxzZQogICAgdGhlbWU6IGRhcmtseQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KE15RnVuY3Rpb25zKQpNeUZ1bmN0aW9uczo6bXlfbGliKGMoImdnbWFwIiwic2YiLCJzdCIsInRpZHl2ZXJzZSIsInRvb2xzIiwicmVhZHIiLCJkYXRhLnRhYmxlIiwibWFwcyIsInZpcmlkaXMiLCJ3ZXNhbmRlcnNvbiIsImtuaXRyIiwia2FibGVFeHRyYSIsInBsb3RseSIsImdncmVwZWwiLCJnZ3NmbGFiZWwiLCJqYW5pdG9yIiwiaW50ZXJwIiwicm5hdHVyYWxlYXJ0aCIsInJlYWR4bCIpKQoKIyBGaXggbmV3IHVwZGF0ZXMgb2Ygc2YgcGFja2FnZQpzZjo6c2ZfdXNlX3MyKHVzZV9zMiA9IEZBTFNFKQoKCiMgQ3JlYXRlIHNwZWNpZmljIHN0YXRlIHBhbGxldCBmcm9tIG91ciBmcmllbmQgV2VzIEFuZGVyc3NvbgpzdGF0ZV9wYWxsZXQgPC0gYyh3ZXNfcGFsZXR0ZShuID0gNSwgbmFtZSA9ICJEYXJqZWVsaW5nMSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2VzX3BhbGV0dGUobiA9IDUsIG5hbWUgPSAiRGFyamVlbGluZzIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdlc19wYWxldHRlKG4gPSAzLCBuYW1lID0gIlJveWFsMSIpCiAgICAgICAgICAgICAgICAgICkKCmBgYAoKIyBNZXRob2RzCgojIyBTcGF0aWFsIGRhdGEgcHJlcGFyYXRpb24KCiMjIyBMb2FkIGRhdGEKCiMjIyMgTWFwcyBkYXRhCgpXZSB1c2UgdGhyZWUgZGlmZmVyZW50IHNoYXBlZmlsZXMgZm9yIHRoZSBjb250aW5lbnRhbCBVLlMuIGxhbmQgbWFzcywgdGhlIFN0YXRlIHdhdGVycyBvZiBtYWluZSwgbmV3IGhhbXBzaGlyZSwgbWFzc2FjaHVzZXRzLCBjb25uZWN0aWN1dCwgcmhvZGUgaXNsYW5kLCBuZXcgeW9yaywgbmV3IGplcnNleSwgZGVsYXdhcmUsIG1hcnlsYW5kLCB2aXJnaW5pYSwgbm9ydGggY2Fyb2xpbmEgYW5kIHRoZSBOb3J0aCBFYXN0IEVFWi4gTW9yZW92ZXIsIHdlIHVzZSB0aGUgTk9BQSBkYXRhc2V0IG9mIGxhbmRpbmdzIHBlciBwb3J0LgoKIyMjIyMgMS4tIExhbmQgc2hhcGVmaWxlCgpDb3ZlcnMgdGhlIFVTIGxhbmQgdGVycml0b3J5IGZvciB2aXN1YWxpemF0aW9uLiBEYXRhIHByb3ZpZGVkIGZyb20gdGhlIGBtYXBgIHBhY2thZ2UuCgoKYGBge3IgbGFuZF9zZiwgZXZhbCA9IFQsIGVjaG8gPSBULCByZXN1bHRzID0gJ2hpZGUnfQoKU3RhdGVzIDwtIGMoIm1haW5lIiwgIm5ldyBoYW1wc2hpcmUiLCAibWFzc2FjaHVzZXR0cyIsICJjb25uZWN0aWN1dCIsICJyaG9kZSBpc2xhbmQiLCAibmV3IHlvcmsiLCAibmV3IGplcnNleSIsICJkZWxhd2FyZSIsICJtYXJ5bGFuZCIsICJ2aXJnaW5pYSIsICJub3J0aCBjYXJvbGluYSIpIAoKIyAtLS0tLS0tLS0tLS0tLSAjCiMgVVMgU3RhdGUgTWFwIChsYW5kKQojIC0tLS0tLS0tLS0tLS0tICMKCmxhbmRfc2YgPC0gc3RfYXNfc2YobWFwKCJzdGF0ZSIsIHBsb3QgPSBGQUxTRSwgZmlsbCA9IFRSVUUpKSAlPiUgCiAgZmlsdGVyKElEICVpbiUgU3RhdGVzKSAlPiUgCiAgbXV0YXRlKGFicmV2ID0gYygiQ1QiLCJERSIsIk1FIiwiTUQiLCJNQSIsIk5IIiwiTkoiLCJOWSIsIk5DIiwiUkkiLCJWQSIpLAogICAgICAgICBzdGF0ZSA9IHN0cl90b19zZW50ZW5jZShJRCkKICAgICAgICAgKQoKIyBWaXN1YWwgZXhwbG9yYXRpb24gKG8uayEgKQpnZ3Bsb3QobGFuZF9zZikgKwogIGdlb21fc2YoYWVzKGZpbGwgPSBzdGF0ZSkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQpICsKICB0aGVtZV9kYXJrKCkKICAgICAgICAgIAoKYGBgCgojIyMjIyAgMi4tIEVFWiBzaGFwZWZpbGUKClVzZWQgdGhlICpTZWEgQXJvdW5kIFVzKiBzaGFwZWZsZSB1cGRhdGVkIHRvIEp1bmUgMjAxNi4KCmBgYHtyIGVlel9zZiwgZXZhbCA9IFQsIGVjaG8gPSBUfQoKIyBVUyBFRVogbWFwCnBhdGhfd29ybGQgPC0gbXlfcGF0aCgiRyIsIGV4dHJhX3BhdGggPSAiU3BhdGlhbC9TQVUvU0FVX1NoYXBlZmlsZSIsIG5hbWUgPSAiU0FVRUVaX0p1bHkyMDE1LnNocCIpCgojIExvYWQgaXQhCmVlel9zZiA8LSBzdF9yZWFkKHBhdGhfd29ybGQpICU+JQogIHJlbmFtZShlZXpfbmFtZSA9IE5hbWUpICU+JQogIHN0X3RyYW5zZm9ybShjcnMgPSA0MzI2KSAlPiUgIyA0MzI2CiAgZmlsdGVyKGVlel9uYW1lID09ICJVU0EgKEVhc3QgQ29hc3QpIikgJT4lCiAgc3Rfc2ltcGxpZnkocHJlc2VydmVUb3BvbG9neSA9IFRSVUUsIGRUb2xlcmFuY2UgPSAwLjEpICMwLjEgZm9yIHBhcGVyCgojIFZpc3VhbCBleHBsb3JhdGlvbiAoby5rISApCmdncGxvdChlZXpfc2YpICsKICBnZW9tX3NmKCkgKwogIHRoZW1lX2RhcmsoKQoKYGBgCgojIyMjIyAgMy4tICBTdGF0ZSB3YXRlcnMKCkNvdmVycyB0aGUgc3RhdGUgd2F0ZXJzIG9mIHRoZSBORSBVUyBzdGF0ZXMuIERhdGEgZnJvbSBbZGF0YS5nb3ZdKGh0dHBzOi8vY2F0YWxvZy5kYXRhLmdvdi9kYXRhc2V0L2ZlZGVyYWwtYW5kLXN0YXRlLXdhdGVycykuICAKCipMaWNlbnNlOiBObyBsaWNlbnNlIGluZm9ybWF0aW9uIHdhcyBwcm92aWRlZC4gSWYgdGhpcyB3b3JrIHdhcyBwcmVwYXJlZCBieSBhbiBvZmZpY2VyIG9yIGVtcGxveWVlIG9mIHRoZSBVbml0ZWQgU3RhdGVzIGdvdmVybm1lbnQgYXMgcGFydCBvZiB0aGF0IHBlcnNvbidzIG9mZmljaWFsIGR1dGllcyBpdCBpcyBjb25zaWRlcmVkIGEgVS5TLiBHb3Zlcm5tZW50IFdvcmsuKgoKYGBge3Igc3RhdGVfc2YsIGV2YWwgPSBULCBlY2hvID0gVH0KCiMgdXNfc3RhdGVfZmlsZSA8LSBteV9wYXRoKCJHIiwgZXh0cmFfcGF0aCA9ICJTcGF0aWFsL1VTRmVkQW5kU3RhdGVXL0ZlZGVyYWxBbmRTdGF0ZVdhdGVycy5nZGIiKQoKc3RhdGVfc2YgPC0gIHN0X3JlYWQoIn4vT25lRHJpdmUgLSBVVy1NYWRpc29uL1NwYXRpYWxfRGF0YS9VU0ZlZEFuZFN0YXRlVy9GZWRlcmFsQW5kU3RhdGVXYXRlcnMuZ2RiIikgJT4lCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUgCiAgbXV0YXRlKGp1cmlzZGljdGkgPSBzdHJfdG9fbG93ZXIoanVyaXNkaWN0aSkpICU+JSAKICBmaWx0ZXIoanVyaXNkaWN0aSAlaW4lIFN0YXRlcykgJT4lIAogIG11dGF0ZShzdGF0ZSA9IHN0cl90b19zZW50ZW5jZShqdXJpc2RpY3RpKSkgJT4lIAogIHN0X3RyYW5zZm9ybShjcnMgPSA0MzI2KSAlPiUgICAjIGZvciBtYXRjaGluZyBwcm9qZWN0aW9ucwogIHN0X3NpbXBsaWZ5KHByZXNlcnZlVG9wb2xvZ3kgPSBUUlVFLCBkVG9sZXJhbmNlID0gMTAwMDApICMwLjEgZm9yIHBhcGVyCgoKIyBWaXN1YWwgZXhwbG9yYXRpb24gKG8uayEgKQpnZ3Bsb3Qoc3RhdGVfc2YpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gc3RhdGUpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSArCiAgdGhlbWVfZGFyaygpCgpgYGAKCiMjIyMjIDQuLSBGaXNoaW5nIHBvcnRzCgpXZSB1c2VkIFtHbG9iYWwgRmlzaGluZyBXYXRjaF0oaHR0cHM6Ly9nbG9iYWxmaXNoaW5nd2F0Y2gub3JnL2RhdGFzZXRzLWFuZC1jb2RlLWFuY2hvcmFnZXMvKSdzIGRhdGFiYXNlIG9uIApBbmNob3JhZ2VzLCBQb3J0cyBhbmQgVm95YWdlcy4KCipUaGUgR2xvYmFsIEZpc2hpbmcgV2F0Y2ggYW5jaG9yYWdlcyBkYXRhc2V0IGlzIGEgZ2xvYmFsIGRhdGFiYXNlIG9mIGFuY2hvcmFnZSBsb2NhdGlvbnMgd2hlcmUgdmVzc2VscyBjb25ncmVnYXRlLiBUaGUgZGF0YXNldCBjb250YWlucyBvdmVyIDE2MCwwMDAgaW5kaXZpZHVhbCBhbmNob3JhZ2UgbG9jYXRpb25zLCB3aGljaCBhcmUgZnVydGhlciBncm91cGVkIGludG8gbmVhcmx5IDMyLDAwMCBwb3J0cyB3aGVuIGFwcGxpY2FibGUuKgoKCmBgYHtyIHBvcnRzX3NmLCBldmFsID0gVCwgZWNobyA9IFR9CgojIEdldCBHbG9iYWwgRmlzaGlnIFdhdGNoIGRhdGEKZ2Z3X2RhdGEgPC0gbXlfcGF0aCgiRCIsIlNwYXRpYWwiLG5hbWUgPSAiZ2Z3X3BvcnRkYXRhLmNzdiIsIHJlYWQgPSBUKSAlPiUgCiAgZmlsdGVyKGlzbzMgPT0gIlVTQSIpIAoKIyBWaXN1YWxpemUgZGF0YSAoby5rISkKIyBnZ3Bsb3QoZ2Z3X2RhdGEpICsKIyAgIGdlb21fcG9pbnQoCiMgICAgIGFlcygKIyAgICAgeCA9IGxvbiwKIyAgICAgeSA9IGxhdAojICAgKQojICAgKQoKIyBDb252ZXJ0IGRhdGEgdG8gc2YgZm9yIG1lcmdpZwpnZndfc2YgPC0gc3RfYXNfc2YoZ2Z3X2RhdGEsCiAgICAgICAgICAgICBjb29yZHMgPSBjKCJsb24iLCAibGF0IiksCiAgICAgICAgICAgICBjcnMgPSA0MzI2KQoKIyBNZXJnZSBkYXRhIHdpdGggc3RhdGUgd2F0ZXJzIHRvLGxvY2F0ZSBwb3J0cyAKcG9ydF9zZiA8LSBzdF9qb2luKGdmd19zZixzdGF0ZV9zZikgJT4lIAogIGZpbHRlcighaXMubmEoanVyaXNkaWN0aSkpICMgcmVtb3ZlIHBvaW50cyBvdXRzaWRlIHN0YXQgd2F0ZXJzCgpnZ3Bsb3QocG9ydF9zZikgICsKICBnZW9tX3NmKGFlcyhjb2xvciA9IGRpc3RhbmNlX2Zyb21fc2hvcmVfbSkpICsKICB0aGVtZV9kYXJrKCkKCmBgYApTby4uLkxvb2tzIGxpa2Ugc29tZSBwb3J0cyBhcmUgImZhciBmcm9tIHNob3JlIiB3aGljaCBJIGRvbid0IHJlYWxseSBrbm93IHdoYXQgaXQgbWVhbnMuIEZvciBub3csIEkgYW0gb25seSBzZWxlY3RpbmcgdGhvc2UgcG9ydHMgdGhhdCBhciAwIG1ldGVyIGZyb20gc2hvcmUuIAoKCmBgYHtyIHBvcnRzX2luc2hvcmUsIGV2YWwgPSBULCBlY2hvID0gRn0KCiMgR2V0IG51bWJlciBvZiBwb3J0cyBwZXIgc3RhdGUKcG9ydHNfbl9kYXRhIDwtIHBvcnRfc2YgJT4lIAogIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgICBmaWx0ZXIoZGlzdGFuY2VfZnJvbV9zaG9yZV9tID09IDApICU+JSAKICAgIGdyb3VwX2J5KHN0YXRlKSAlPiUgCiAgICBzdW1tYXJpc2Uobl9wb3J0cyA9IG4oKSkgCgojIHBsb3QgaXQKZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UoCiAgcG9ydF9zZiAlPiUgCiAgICBmaWx0ZXIoZGlzdGFuY2VfZnJvbV9zaG9yZV9tID09IDApICU+JSAKICAgIGdncGxvdCgpICArCiAgICBnZW9tX3NmKGFlcyhjb2xvciA9IGp1cmlzZGljdGkpKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSArCiAgICB0aGVtZV9kYXJrKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIiIpLAogIHRhYmxlR3JvYihwb3J0c19uX2RhdGEpLAogIG5jb2wgPSAyCikKCgpgYGAKCgpUaGVyZSBhcmUgc3RpbGwgdG9vIG1hbnkgcG9ydHMgaW4gZWFjaCBzdGF0ZSAoPykuIFNwZWNpYWxseSBOZXcgSmVyc2V5ISBPbmUgYXBwcm9hY2ggaXMgdG8gdXNlIE5PQUEncyBsYW5kaW5nLXBlci1wb3J0IGRhdGEgdG8gZmlsdGVyIG91dC4uLiAKCiMjIyMjIyA0LjEgTk9BQSdzIGRhdGEKClRoaXMgZGF0YXNldCBpbmNsdWRlcyBhbGwgbGFuZGluZ3MgZnJvbSAyMDE1LUp1bHkgMjAyMS4gSXQgaW5jbHVkZXMgdGhlIHNwZWNpZXMgbGFuZGVkLCB0aGUgcG9ydCwgYW5kIHRoZSBIdWxsIElEIGFuZCB2ZXNzZWwgbmFtZSBmb3IgYmxhY2sgc2VhIGJhc3MgYW5kIHN1bW1lciBmbG91bmRlci4KCipMaWNlbnNlLCBmcm9tIFNhcmFoIFNtaXRoOiBUaGlzIGlzIGNvbmZpZGVudGlhbCBkYXRhLCBzbyBwbGVhc2UgZG8gbm90IHNoYXJlIHRoaXMgZmlsZSB3aXRoIG90aGVycy4gWW91IG1heSBuZWVkIHRvIGNvbnRhY3QgTk9BQSBkaXJlY3RseSBqdXN0IHRvIHJlcXVlc3QgcGVybWlzc2lvbi4gTXkgY29udGFjdCBoYXMgYmVlbiBBbGlzb24gRmVyZ3Vzb24gKEFsaXNvbi5GZXJndXNvbkBub2FhLmdvdikgaW4gdGhlaXIgZGF0YSBkZXBhcnRtZW50LioKCmBgYHtyfQoKIyMjIFNSQUggTEFORElORyBEQVRBCnJlYWRfZXhjZWxfYWxsc2hlZXRzIDwtIGZ1bmN0aW9uKGZpbGVuYW1lLCB0aWJibGUgPSBUUlVFKSB7CiAgICAjIEkgcHJlZmVyIHN0cmFpZ2h0IGRhdGEuZnJhbWVzCiAgICAjIGJ1dCBpZiB5b3UgbGlrZSB0aWR5dmVyc2UgdGliYmxlcyAodGhlIGRlZmF1bHQgd2l0aCByZWFkX2V4Y2VsKQogICAgIyB0aGVuIGp1c3QgcGFzcyB0aWJibGUgPSBUUlVFCiAgICBzaGVldHMgPC0gcmVhZHhsOjpleGNlbF9zaGVldHMoZmlsZW5hbWUpWzI6OF0KICAgIHggPC0gbGFwcGx5KHNoZWV0cywgZnVuY3Rpb24oWCkgcmVhZHhsOjpyZWFkX2V4Y2VsKGZpbGVuYW1lLCBzaGVldCA9IFgpKQogICAgaWYoIXRpYmJsZSkgeCA8LSBsYXBwbHkoeCwgYXMuZGF0YS5mcmFtZSkKICAgIG5hbWVzKHgpIDwtIHNoZWV0cwogICAgeAp9CiMgR2V0IGRhdGEgcGF0aApwb3J0c19wYXRoIDwtIG15X3BhdGgoIkQiLCJOT0FBIiwgbmFtZSA9ICJTU21pdGhfMjAxNS0yMDIxIExhbmRpbmdzX0pVTiAyMDIxLnhsc3giKQoKIyAKcG9ydHNfZGF0YSA8LSBiaW5kX3Jvd3MocmVhZF9leGNlbF9hbGxzaGVldHMocG9ydHNfcGF0aCkpICU+JQogIGNsZWFuX25hbWVzKCkgJT4lCiAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwKICAgICAgICAgICAgICB+IHN0cl90b19sb3dlciguKSkgJT4lIAogIG11dGF0ZShsYW5kaW5nX3BvcnQgPSBzdHJfcmVtb3ZlKGxhbmRpbmdfcG9ydCwiWzpibGFuazpdXFwoc3RhdGVcXCkiKSkKCm5vYWFfcG9ydHMgPC0gdW5pcXVlKHBvcnRzX2RhdGEkbGFuZGluZ19wb3J0KQoKbm9hYV9wb3J0IDwtIHBvcnRfc2YgJT4lIAogIGZpbHRlcihkaXN0YW5jZV9mcm9tX3Nob3JlX20gPT0gMCkgJT4lIAogIG11dGF0ZShsYWJlbCA9IHN0cl90b19sb3dlcihsYWJlbCkpICU+JSAKICBmaWx0ZXIobGFiZWwgJWluJSBub2FhX3BvcnRzKQoKIyBHZXQgbnVtYmVyIG9mIHBvcnRzIHBlciBzdGF0ZQpub2FhX3BvcnRzX25fZGF0YSA8LSBub2FhX3BvcnQgJT4lIAogIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgICBncm91cF9ieShzdGF0ZSkgJT4lIAogICAgc3VtbWFyaXNlKG5vYWFfcG9ydHMgPSBuKCkpIAoKIyBHZXQgbnVtYmVyIG9mIHBvcnRzIGluIHRoZSBOT0FBIGRhdGFiYXNlCgpuX3BvcnRzX2RhdGEgPC0gcG9ydHNfZGF0YSAlPiUgCiAgZ3JvdXBfYnkobGFuZGluZ19zdGF0ZSkgJT4lIAogIHN1bW1hcmlzZShub2FhX3BvcnRzID0gbGVuZ3RoKHVuaXF1ZShsYW5kaW5nX3BvcnQpKSkgJT4lIAogIG11dGF0ZShhYnJldiA9IHN0cl90b191cHBlcihsYW5kaW5nX3N0YXRlKSkgJT4lIAogIGxlZnRfam9pbihsYW5kX3NmKSAlPiUgCiAgc2VsZWN0KHN0YXRlLG5vYWFfcG9ydHMpICU+JSAKICBmaWx0ZXIoIWlzLm5hKHN0YXRlKSkgJT4lIAogIGxlZnRfam9pbihub2FhX3BvcnRzX25fZGF0YSkKCiMgcGxvdCBpdApncmlkRXh0cmE6OmdyaWQuYXJyYW5nZSgKICBwb3J0X3NmICU+JSAKICAgIG11dGF0ZShsYWJlbCA9IHN0cl90b19sb3dlcihsYWJlbCkpICU+JSAKICAgIGZpbHRlcihkaXN0YW5jZV9mcm9tX3Nob3JlX20gPT0gMCwKICAgICAgICAgICBsYWJlbCAlaW4lIG5vYWFfcG9ydHMKICAgICAgICAgICApICU+JSAKICAgIGdncGxvdCgpICArCiAgICBnZW9tX3NmKGFlcyhjb2xvciA9IGp1cmlzZGljdGkpKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSArCiAgICB0aGVtZV9kYXJrKCksCiAgICAjIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICIiKSwKICB0YWJsZUdyb2Iobl9wb3J0c19kYXRhKSwKICBuY29sID0gMgopCiAgCmBgYAoKClRoaXMgYXBwcm9hY2ggcmVtb3ZlcyBhIGxvdCBvZiBwb3J0cyB0byB0aGUgcG9pbnQgdGhhdCBEZWxhd2FyZSBpcyBjb21wbGV0ZWx5IHBvcnQtbGVzcwoKIyMjIyMjIDQuMiBXb3JsZCBQb3J0IEluZGV4IAoKSW4gdGhpcyBhcHByb2FjaCB3ZSBvbmx5IHVzZSB0aGUgcG9ydHMgY2F0ZWdvcml6ZWQgd2l0aGluIHRoZSBbV1BJXShodHRwczovL21zaS5uZ2EubWlsL05HQVBvcnRhbC9NU0kucG9ydGFsP19uZnBiPXRydWUmX3BhZ2VMYWJlbD1tc2lfcG9ydGFsX3BhZ2VfNjImcHViQ29kZT0wMDE1KSBhbmQgd2l0aCBgZGlzdGFuY2VfZnJvbV9zaG9yZV9tID09IDBgICBhbmQgYGF0X2RvY2sgPT0gVFJVRWAuCgotIGBhdF9kb2NrYCA9PSBBbmNob3JhZ2VzIHdpdGhpbiBhIDQ1MCBtZXRlciBidWZmZXIgYXJvdW5kIGEgY29tYmluZWQgbGFuZCBzaGFwZSBmaWxlIGFyZSBjb25zaWRlcmVkIGF0IGRvY2suIAoKYGBge3Igd3BpX2FwcHJvYWNoLCBldmFsID0gVCwgZWNobyA9IEZ9CgpncmlkRXh0cmE6OmdyaWQuYXJyYW5nZSgKICBwb3J0X3NmICU+JSAKICAgIGZpbHRlcihkaXN0YW5jZV9mcm9tX3Nob3JlX20gPT0gMCwKICAgICAgICAgICBsYWJlbF9zb3VyY2UgJWluJSBjKCJXUElfcG9ydHMiKSwKICAgICAgICAgICBhdF9kb2NrID09IFRSVUUpICU+JSAKICAgIGdncGxvdCgpICArCiAgICBnZW9tX3NmKGFlcyhjb2xvciA9IGp1cmlzZGljdGkpKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSArCiAgICB0aGVtZV9kYXJrKCksCiAgcG9ydF9zZiAlPiUgCiAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogICAgZmlsdGVyKGRpc3RhbmNlX2Zyb21fc2hvcmVfbSA9PSAwLAogICAgICAgICAgIGxhYmVsX3NvdXJjZSAlaW4lIGMoIldQSV9wb3J0cyIpLAogICAgICAgICAgIGF0X2RvY2sgPT0gVFJVRSkgJT4lIAogICAgZ3JvdXBfYnkoc3RhdGUpICU+JSAKICAgIHN1bW1hcmlzZShuX3BvcnRzID0gbigpKSAlPiUgCiAgICB0YWJsZUdyb2IoKSwKICBuY29sID0gMgopCgoKYGBgCgpUaGlzIGFwcHJvYWNoIG1pZ2h0IGJlIGJldHRlciBzdWl0ZWQuIEl0IGFsc28gaGFzIHRlaCBhZHZhbnRhZ2UgdGhhdCB3ZSBhcmUgdXNpbmcgdGhlIFdQSS4KClRoaXMgaXMgaG93IGFsbCB0aGUgc2hhcGVmaWxlcyBsb29rIGxpa2UgdG9nZXRoZXIKCgpgYGB7ciBhbGxfc2YsIGV2YWwgPSBULCBlY2hvID0gVH0KCnBvcnRfc2YgPC0gcG9ydF9zZiAlPiUgCiAgICBmaWx0ZXIoZGlzdGFuY2VfZnJvbV9zaG9yZV9tID09IDAsCiAgICAgICAgICAgbGFiZWxfc291cmNlICVpbiUgYygiV1BJX3BvcnRzIiksCiAgICAgICAgICAgYXRfZG9jayA9PSBUUlVFKQoKIyBWaXN1YWwgZXhwbG9yYXRpb24gb2YgYWxsIHRvZ2V0aGVyIChvLmshICkKZ2dwbG90KCkgKwogIGdlb21fc2YoZGF0YSA9IGVlel9zZiwgYWVzKCkpICsKICBnZW9tX3NmKGRhdGEgPSBsYW5kX3NmLCBhZXMoZmlsbCA9IHN0YXRlKSwgYWxwaGEgPSAwLjMpICsKICBnZW9tX3NmKGRhdGEgPSBzdGF0ZV9zZiwgYWVzKGNvbG9yID0gc3RhdGUpLCBmaWxsID0gTkEpICsKICBnZW9tX3NmKGRhdGEgPSBwb3J0X3NmLCBhZXMoY29sb3IgPSBzdGF0ZSkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSArCiAgdGhlbWVfZGFyaygpICsKICBjb29yZF9zZih5bGltID0gYygzMyw0OCkpCgpgYGAKCgojIyMgQ3JlYXRlIGJhc2Ugc2hhcGVmaWxlIGZvciBjb21wdXRhdGlvbgoKQXMgYSBmaXJzdCBzdGVwIHdlIG5lZWQgdG8gZGl2aWRlIHRoZSBORSBVUyBFRVogYW1vbmcgdGhlIGRpZmZlcmVudCBzdGF0ZXMuIEZvciB0aGF0LCB3ZSBleHBhbmRlZCBhIGJ1ZmZlci1wb2x5Z29uIHRvIHRoZSAyMDAgbmF1dGljYWwgbWlsZXMgdG8gdGhlbiBlc3RpbWF0ZSB0aGUgcGVyY2VudGFnZSB0aGF0IGVhY2ggZXhwYW5kZWQgcG9seWdvbiBvY2N1cGllZC4gRm9yIHRoZSBpbml0aWFsIGJ1ZmZlciBwb2ludCB3ZSB1c2VkIHR3byBhcHByb2FjaGVzOyBzdGF0ZSB3YXRlcnMgYW5kIFVTIHBvcnRzLiBOb3RlIHRoYXQgaW4gYWxsIGNhc2VzIHRoZXNlIGFyZWFzIG92ZXJsYXBwZWQgYW5kIHBlcmNlbnRhZ2VzIGFjY291bnRlZCBmb3IgaXQuIFdlIGRpZCB0aGlzIGJ5IGZvbGxvd2luZyB0aGVzZSBzdGVwczoKCi0gMS4gRXhwYW5kIHN0YXRlIHdhdGVycyAvIFVTIHBvcnRzIHVzaW5nIGEgYnVmZmVyCgotIDIuIEdyaWQgdGhhdCBidWZmZXIgb24gYSAwLjMgcmVzb2x1dGlvbgoKLSAzLiBDcm9wIHRoZSBidWZmZXIgdG8gdGhlIEVFWgoKIyMjIyAxLiBFeHBhbmQgU3BhdGlhbCByZWdpb25zIChhLmsuYSAgYnVmZmVycykKCiMjIyMjIDEuMSBTdGF0ZSBXYXRlcnMKCldlIHNldCBhIGJ1ZmZlciBvZiAqNDEwMDAwKiBtICg0MTAga20sIH4gMjIxIG5tKSB0aGF0IG92ZXJzaG9vdHMgdGhlIEVFWiBhIGJpdCwgYnV0IGlzIGV2ZW50dWFsbHkgY3JvcHBlZAoKYGBge3Igc3dfYnVmZmVyLCBldmFsID0gVCwgZWNobyA9IFR9CgojIEJ1ZmZlciBzdGF0ZSB3YXRlcnMKc3RhdGVfYmYgPSBzdF9idWZmZXIoc3RhdGVfc2YsIDQpICU+JSAKICBzdF90cmFuc2Zvcm0oNDMyNikgJT4lICMgdG8gbWF0Y2ggc2hhcGUKICBzdF9zZXRfY3JzKDQzMjYpCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAjCiMgVGVzdGluZyBhbmQgdmlzdWFsaXppbmcgdGhlIGJ1ZmZlciAKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIwoKc3RhdGVfYmZfcGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9zZihkYXRhID0gc3RhdGVfc2YsIGFlcyhjb2xvciA9IHN0YXRlKSwgZmlsbCA9IE5BKSArCiAgZ2VvbV9zZihkYXRhID0gZWV6X3NmLCBhZXMoKSwgZmlsbCA9IE5BKSArCiAgZ2VvbV9zZihkYXRhID0gc3RhdGVfYmYsIGFlcyhjb2xvciA9IHN0YXRlKSwgZmlsbCA9IE5BKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHN0YXRlX3BhbGxldCkrCiAgdGhlbWVfZGFyaygpCiMgICAKCiMgZ2dzYXZlKCIuLi9SZXN1bHRzL1BhcnRpYWwvc3RhdGVfd2F0ZXJzX2J1ZmZlci5wbmciLHN0YXRlX2JmX3Bsb3QpCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAjCgpzdGF0ZV9iZl9wbG90CgpgYGAKCiMjIyMjIDEuMSBVUy4gUG9ydHMKCldlIHNldCBhIGJ1ZmZlciBvZiAqNSogZGVnICg1MTAga20sIH4gMjIxIG5tKSB0aGF0IG92ZXJzaG9vdHMgdGhlIEVFWiBhIGJpdCwgYnV0IGlzIGV2ZW50dWFsbHkgY3JvcHBlZAoKYGBge3IgZnBfYnVmZmVyLCBldmFsID0gVCwgZWNobyA9IFR9CgojIEJ1ZmZlciBzdGF0ZSB3YXRlcnMKcG9ydF9iZiA9IHN0X2J1ZmZlcihwb3J0X3NmLCA1KSAlPiUgIyBwb3J0CiAgc3RfdHJhbnNmb3JtKDQzMjYpICU+JSAjIHRvIG1hdGNoIHNoYXBlCiAgc3Rfc2V0X2Nycyg0MzI2KQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIwojIFRlc3RpbmcgYW5kIHZpc3VhbGl6aW5nIHRoZSBidWZmZXIgCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICMKCmdncGxvdCgpICsKICBnZW9tX3NmKGRhdGEgPSBlZXpfc2YsIGFlcygpLGZpbGwgPSBOQSkgKwogIGdlb21fc2YoZGF0YSA9IHBvcnRfYmYsIGFlcyhjb2xvciA9IHN0YXRlKSwgZmlsbCA9IE5BKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHN0YXRlX3BhbGxldCkrCiAgdGhlbWVfZGFyaygpCgpgYGAKCgojIyMjIDIuIEV4cGFuZCBncmlkIHdpdGhpbiBidWZmZXIKCkhlcmUgd2UgZXhwYW5kIGEgZ3JpZCB3aXRoaW4gdGhlIGJ1ZmZlciBzbyB3ZSBjYW4gZXN0aW1hdGUgdGhlIHByb3BvcnRpb24gb2YgZWFjaCBzdGF0ZS4KCipOb3RlOiogRGFyayBncmV5IHNoYWRlZCBhcmVhIGlzIHRoZSBncmlkIGFuZCBpcyB0aGUgc2FtZSBmb3IgYm90aCBhcHByb2FjaGVzCgpgYGB7ciBncmlkX2luZGV4aW5nLCBldmFsID0gVCwgZWNobyA9IFQsIG1lc3NhZ2UgPSBGLCB3YXJuaW5nID0gRn0KCiMgQ3JlYXRlIGdyaWQgb2YgdGhlIHJlZ2lvbgpiYm94IDwtIGMoc3RfYmJveChzdGF0ZV9iZikpCgojIEV4cGFuZCB0aGUgZ3JpZApuZV9ncmlkIDwtIGV4cGFuZC5ncmlkKAogICAgbG9uID0gc2VxKGZyb20gPSBiYm94WyJ4bWluIl0sIHRvID0gYmJveFsieG1heCJdLCBieSA9IDAuMyksCiAgICBsYXQgPSBzZXEoZnJvbSA9IGJib3hbInltaW4iXSwgdG8gPSBiYm94WyJ5bWF4Il0sIGJ5ID0gMC4zKQopICU+JSAKICByb3dpZF90b19jb2x1bW4oImluZGV4IikKCiMgLS0tLS0tLS0tLS0gIwojIFtURVNUXSBQbG90IGFsbCBsYXllcnMKIyAtLS0tLS0tLS0tLSAjCgojIExvb2tzIGdvb2QKc3RhdGVfc2YgJT4lCiAgc3RfdHJhbnNmb3JtKDQzMjYpICU+JSAjIHRvIG1hdGNoIHNoYXBlCiAgc3Rfc2V0X2Nycyg0MzI2KSAlPiUKICAjIHN0X3NpbXBsaWZ5KHByZXNlcnZlVG9wb2xvZ3kgPSBUUlVFLCBkVG9sZXJhbmNlID0gMTAwMDApICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhjb2xvciA9IHN0YXRlKSkrCiAgIyBnZW9tX3NmKGRhdGEgPSBlZXpfc2YsIGFlcygpLGZpbGwgPU5BKSArCiAgIyBnZ3Bsb3QoKSsKICBnZW9tX3RpbGUoZGF0YSA9IG5lX2dyaWQsCiAgICAgICAgICAgIGFlcygKICAgICAgICAgICAgICB4ID0gbG9uLAogICAgICAgICAgICAgIHkgPSBsYXQKICAgICAgICAgICAgKSwKICAgICAgICAgICAgYWxwaGEgPSAwLjIKICApICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWVfZGFyaygpCgoKYGBgCgojIyMjIyAyLjEgTWVyZ2UgZ3JpZCBhbmQgYnVmZmVycwoKT25jZSB3ZSBoYXZlIGEgZ3JpZGRlZCBhcmVhLCB3ZSBjb252ZXJ0ZWQgdGhlIGdyaWQgdG8gYSBgc2ZgIHNvIHdlIGNhbiBtZXJnZSBpdCB3aXRoIHRoZSBidWZmZXJlZCBzdGF0ZXMgYW5kIHBvcnRzIGFuZCBmaW5hbGx5IGZpbHRlciBvdXQgZXZlcnl0aGluZyBvdXRzaWRlIHRoZSBzdGF0ZXMgcG9seWdvbgoKIyMjIyMjIDIuMS4xIFN0YXRlIFdhdGVycwoKYGBge3IgZ3JpZF9zd19idWZfbWVyZ2UsIGV2YWwgPSBULCBlY2hvID0gVCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGLCBmaWcud2lkdGggPSAxMH0KCiMgLS0tLS0tLS0tLS0tLS0tLSAjCiMgQ29udmVydCBncmlkIHRvIHNmCiMgLS0tLS0tLS0tLS0tLS0tLSAjCmdyaWRfc3dfc2YgPC0gc3RfYXNfc2YobmVfZ3JpZCwKICAgICAgICAgICAgIGNvb3JkcyA9IGMoImxvbiIsICJsYXQiKSwKICAgICAgICAgICAgIGNycyA9IDQzMjYpICU+JSAKICBzdF9qb2luKHN0YXRlX2JmKSAlPiUgCiAgZmlsdGVyKCFpcy5uYShzdGF0ZSkpCgojIENyZWF0ZSBkYXRhIGZyYW1lIGZvciBmdXR1cmUgY29tcHV0YXRpb25zCiMgTm90ZSwgd2lsbCBiZSB1c2VkIGluIG5leHQgY2h1bmsKZ3JpZF9zd19iZl9kdCA8LSBhcy5kYXRhLmZyYW1lKGdyaWRfc3dfc2YpICU+JQogICAgc2VsZWN0KGluZGV4LHN0YXRlKQogICAgIyBncm91cF9ieShzdGF0ZSkgJT4lIAogICAgIyBzdW1tYXJpc2UobGVuZ3RoKGluZGV4KSkKCgojIC0tLS0tLS0tLS0tLS0tLS0gIwojIFtURVNUXSAKIyBWaXN1YWxpemF0aW9uIG9mIGdyaWQKIyAtLS0tLS0tLS0tLS0tLS0tICMKCmdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKAogICMgT3ZlcmFsbCAob3ZlcmxhcHBpbmcpIHBvc2l0aW9uCiAgZ2dwbG90KGdyaWRfc3dfc2YpICsKICAgIGdlb21fc2YoZGF0YSA9IHN0YXRlX3NmLCBhZXMoKSwgZmlsbCA9IE5BKSArCiAgICBnZW9tX3NmKGFlcyhjb2xvciA9IHN0YXRlKSwgYWxwaGEgPSAwLjMpICsKICAgIGdlb21fc2YoZGF0YSA9IGVlel9zZiwgYWVzKCksZmlsbCA9TkEpICsgCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSArCiAgICB0aGVtZV9kYXJrKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIiIpLAogICMgU2hvd2luZyBlYWNoIHN0YXRlIHNlcGFyYXRsZXkKICBnZ3Bsb3QoKSArCiAgICBnZW9tX3NmKGRhdGEgPSBncmlkX3N3X3NmLCBhZXMoY29sb3IgPSBzdGF0ZSksc2l6ZSA9IDAuMSwgYWxwaGEgPSAwLjUpICsKICAgIGZhY2V0X3dyYXAofnN0YXRlKSArCiAgICB0aGVtZV9kYXJrKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQpLAogIG5yb3cgPSAxKSAKCmBgYAoKIyMjIyMjIDIuMS4xIEZpc2hpbmcgUG9ydHMKCmBgYHtyIGdyaWRfZnBfYnVmX21lcmdlLCBldmFsID0gVCwgZWNobyA9IFQsIG1lc3NhZ2UgPSBGLCB3YXJuaW5nID0gRiwgZmlnLndpZHRoID0gMTB9CgojIC0tLS0tLS0tLS0tLS0tLS0gIwojIENvbnZlcnQgZ3JpZCB0byBzZgojIC0tLS0tLS0tLS0tLS0tLS0gIwpncmlkX2ZwX3NmIDwtIHN0X2FzX3NmKG5lX2dyaWQsCiAgICAgICAgICAgICBjb29yZHMgPSBjKCJsb24iLCAibGF0IiksCiAgICAgICAgICAgICBjcnMgPSA0MzI2KSAlPiUgCiAgc3Rfam9pbihwb3J0X2JmKSAlPiUgIyBqb2luIHRvIHBvcnQgc2YKICBmaWx0ZXIoIWlzLm5hKHN0YXRlKSkgJT4lIAogIGRpc3RpbmN0KGluZGV4LHN0YXRlLCAua2VlcF9hbGwgPSBUUlVFKSAjcmVtb3ZlcyBsaWtlIDQwMEsgb3ZlcmxhcHBpbmcgcm93cwoKIyBDcmVhdGUgZGF0YSBmcmFtZSBmb3IgZnV0dXJlIGNvbXB1dGF0aW9ucwojIE5vdGUsIHdpbGwgYmUgdXNlZCBpbiBuZXh0IGNodW5rCmdyaWRfZnBfYmZfZHQgPC0gYXMuZGF0YS5mcmFtZShncmlkX2ZwX3NmKSAlPiUKICAgIHNlbGVjdChpbmRleCxzdGF0ZSkKCiMgLS0tLS0tLS0tLS0tLS0tLSAjCiMgW1RFU1RdIAojIFZpc3VhbGl6YXRpb24gb2YgZ3JpZAojIC0tLS0tLS0tLS0tLS0tLS0gIwoKZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UoCiAgIyBPdmVyYWxsIChvdmVybGFwcGluZykgcG9zaXRpb24KICBnZ3Bsb3QoZ3JpZF9mcF9zZikgKwogICAgZ2VvbV9zZihkYXRhID0gcG9ydF9zZiwgYWVzKCksIGZpbGwgPSBOQSkgKwogICAgZ2VvbV9zZihhZXMoY29sb3IgPSBzdGF0ZSksIGFscGhhID0gMC4zKSArCiAgICBnZW9tX3NmKGRhdGEgPSBlZXpfc2YsIGFlcygpLGZpbGwgPU5BKSArIAogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHN0YXRlX3BhbGxldCkgKwogICAgdGhlbWVfZGFyaygpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICIiKSwKICAjIFNob3dpbmcgZWFjaCBzdGF0ZSBzZXBhcmF0ZWx5CiAgZ2dwbG90KCkgKwogICAgZ2VvbV9zZihkYXRhID0gZ3JpZF9mcF9zZiwgYWVzKGNvbG9yID0gc3RhdGUpLHNpemUgPSAwLjEsIGFscGhhID0gMC41KSArCiAgICBmYWNldF93cmFwKH5zdGF0ZSkgKwogICAgdGhlbWVfZGFyaygpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSwKICBucm93ID0gMSkKCmBgYAoKIyMjIyAzLiBDcm9wIGJ1ZmZlcnMgdG8gRUVaCgpGaW5hbGx5LCB3ZSBjcm9wIHRoZSBncmlkZWQgYnVmZmVycyB0byB3aXRoaW4gdGhlIEVFWiB0byBjYXB0dXJlIHRoZSBhY3R1YWwgd2F0ZXIgc3BhY2UuCgoqTm90ZToqIFRoaXMgc3RlcCB0YWtlcyBxdWl0ZSBhIHdoaWxlIGJlY2F1c2Ugb2YgdGhlIHNpemUgb2YgdGhlIEVFWiBzaGFwZWZpbGUuIE5vLCB5b3UgY2Fubm90IHVzZSBgc3Rfc2ltcGxpZnkoKWAgaGVyZQoKIyMjIyAzLjEgU3RhdGUgV2F0ZXJzCgpgYGB7ciBidWZmX3N3X3RvX2VleiwgZXZhbCA9VCwgZWNobyA9IFQsIG1lc3NhZ2UgPSBGLCB3YXJuaW5nID0gRn0KCiMgSSBkb24ndCBrbm93IGhvdyB0byB1bmRvIHN0X3NpbXBsaWZ5IHNvIG5lZWQgdG8gcmUtbG9hZCB0aGUgc2hhcGVmaWxlCgplZXpfc2YgPC0gc3RfcmVhZChteV9wYXRoKCJHIiwgZXh0cmFfcGF0aCA9ICJTcGF0aWFsL1NBVS9TQVVfU2hhcGVmaWxlIiwgbmFtZSA9ICJTQVVFRVpfSnVseTIwMTUuc2hwIikpICU+JSAKICByZW5hbWUoZWV6X25hbWUgPSBOYW1lKSAlPiUgCiAgc3RfdHJhbnNmb3JtKGNycyA9IDQzMjYpICU+JSAjIDQzMjYKICBmaWx0ZXIoZWV6X25hbWUgPT0gIlVTQSAoRWFzdCBDb2FzdCkiKSAKCiMgR2V0IHRoZSBvdmVybGFwcGluZyBzZWdtZW50cyAKIyBOT1RFOiBUYWtlcyBzb21lIGdvb29vb29kIHRpbWUgKH4yMCBtaW4pClN5cy50aW1lKCkKZ3JpZF9lZXpfc2Zfc3cgPC0gc3RfaW50ZXJzZWN0aW9uKGdyaWRfc3dfc2YsZWV6X3NmKQpTeXMudGltZSgpCiMgd3JpdGVfc2YoZ3JpZF9lZXpfc2YsIHBhc3RlMChteV9wYXRoKCJEIiwgIlNwYXRpYWwiKSwiZ3JpZF9lZXpfc2Yuc2hwIikpCgojIEdldCBmaW5hbCBkZiB3aXRoIGluZGV4CmdyaWRfZWV6X3N3X2RmIDwtIGFzLmRhdGEuZnJhbWUoZ3JpZF9lZXpfc2Zfc3cpICU+JQogIHNlbGVjdChzdGF0ZSxpbmRleCkgJT4lCiAgbGVmdF9qb2luKG5lX2dyaWQsCiAgICAgICAgICAgIGJ5ID0gImluZGV4IikKCiMgd3JpdGVfY3N2KGdyaWRfZWV6X2RmLCBwYXN0ZTAobXlfcGF0aCgiUiIsICJQYXJ0aWFsIiksImdyaWRfZWV6X2RmLmNzdiIpKQoKIyBQbG90IHRvIG1ha2Ugc3VyZSBtYWtlcyBzZW5zZQoKZWV6X3NmIDwtIGVlel9zZiAlPiUgCiAgc3Rfc2ltcGxpZnkocHJlc2VydmVUb3BvbG9neSA9IFRSVUUsIGRUb2xlcmFuY2UgPSAwLjEpICMwLjEgZm9yIHBhcGVyCgpncmlkX2Vlel9zZl9zdyAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZihhZXMoY29sb3IgPSBzdGF0ZSksIGFscGhhID0gMC4zKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHN0YXRlX3BhbGxldCkgKwogIGdlb21fc2YoZGF0YSA9IGVlel9zZixhZXMoKSwgZmlsbCA9IE5BKSArCiAgdGhlbWVfZGFyaygpCgpgYGAKCgojIyMjIDMuMiBGaXNoaW5nIFBvcnRzCgpgYGB7ciBidWZmX2ZwX3RvX2VleiwgZXZhbCA9VCwgZWNobyA9IFQsIG1lc3NhZ2UgPSBGLCB3YXJuaW5nID0gRn0KCiMgR2V0IHRoZSBvdmVybGFwcGluZyBzZWdtZW50cyAKIyBOT1RFOiBUYWtlcyBzb21lIGdvb29vb29kIHRpbWUgKH4yMCBtaW4pClN5cy50aW1lKCkKZ3JpZF9lZXpfc2ZfZnAgPC0gc3RfaW50ZXJzZWN0aW9uKGdyaWRfZnBfc2YsZWV6X3NmKQpTeXMudGltZSgpCgojIHdyaXRlX3NmKGdyaWRfZWV6X3NmX2ZwLCBwYXN0ZTAobXlfcGF0aCgiRCIsICJTcGF0aWFsL2dyaWRfZWV6X2ZwX3NmIiksImdyaWRfZWV6X2ZwLnNocCIpKQoKIyBHZXQgZmluYWwgZGYgd2l0aCBpbmRleApncmlkX2Vlel9mcF9kZiA8LSBhcy5kYXRhLmZyYW1lKGdyaWRfZWV6X3NmX2ZwKSAlPiUKICBzZWxlY3Qoc3RhdGUsaW5kZXgpICU+JQogIGxlZnRfam9pbihuZV9ncmlkLAogICAgICAgICAgICBieSA9ICJpbmRleCIpCgp3cml0ZV9jc3YoZ3JpZF9lZXpfZnBfZGYsIHBhc3RlMChteV9wYXRoKCJSIiwgIlBhcnRpYWwiKSwiZ3JpZF9lZXpfZnBfZGYuY3N2IikpCgojIFBsb3QgdG8gbWFrZSBzdXJlIG1ha2VzIHNlbnNlCmdyaWRfZWV6X3NmX2ZwICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhjb2xvciA9IHN0YXRlKSwgYWxwaGEgPSAwLjMpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSArCiAgZ2VvbV9zZihkYXRhID0gZWV6X3NmLGFlcygpLCBmaWxsID0gTkEpICsKICB0aGVtZV9kYXJrKCkKCmBgYAoKIyMjIyAzLjMgRGlmZmVyZW5jZXMgYXQgY3JvcGVkIGxldmVsCgpCeSBsb29raW5nIGF0IHRoZSBwbG90cyB3ZSBkbyBub3Qgc2VlIHRoYXQgdGhlIG51bWJlciBvZiBncmlkIGNlbGxzIHRoYXQgZWFjaCBzdGF0ZSBoYXMgaXMgc2xpZ2h0bHkgZGlmZmVyZW50IGRlcGVuZGluZyBvbiB0aGUgYXBwcm9hY2guIFRoaXMgY29tZXMgdG8gbGlnaHQgd2hlbiB3ZSBjb3VudCB0aGUgbnVtYmVyIG9mIGdyaWRjZWxscyB0aGF0IGVhY2ggc3RhdGUgZ2V0cyBpbiBlYWNoIGFwcHJvYWNoLiBXZSBzZWUgdGhhdCB0aGUgc3RhdGUgd2F0ZXJzIG9uZSBpcyBzdWJzdGFudGlhbGx5IGhpZ2hlci4KCldlIGNhbiB2aXN1YWxpemUgdGhlIGRpZmZlcmVuY2Ugb2YgdGhlIGNyb3BwZWQgYXJlYSBmb3IgZWFjaCBzdGF0ZSBuZXh0LiBBZ2FpbiwgdGhlIGZpc2hpbmcgcG9ydCBhcHByb2FjaCByZXN1bHRzIGluIGxlc3MgYXJlYSBmb3IgYWxsIHN0YXRlcywgYnV0IHN1Y2ggYXJlYSBpcyBub3QgcHJvcG9ydGlvbmFsIGFtb25nIHN0YXRlcy4gRm9yIGV4YW1wbGUsIERlbGF3YXJlIGxvb3NlcyByb3VnaGx5IDM1JSBvZiBmaXNoaW5nIGdyb3VuZHMgd2l0aCB0aGlzIGFwcHJvYWNoCgpgYGB7ciBzdGF0ZV9iZl9kaWZmX250YmwsIGV2YWwgPSBULCBlY2hvID0gVH0KCmdyaWRfZWV6X3N3X2RmICU+JSAKICBtdXRhdGUoYXBwcm9hY2ggPSAic3RhdGVfd2F0ZXJzIikgJT4lIAogIGJpbmRfcm93cyhncmlkX2Vlel9mcF9kZikgJT4lCiAgbXV0YXRlKGFwcHJvYWNoID0gaWZlbHNlKGlzLm5hKGFwcHJvYWNoKSwiZmlzaGluZ19wb3J0IixhcHByb2FjaCkpICU+JSAKICBncm91cF9ieShzdGF0ZSxhcHByb2FjaCkgJT4lIAogIHN1bW1hcmlzZShuX2dyaWQgPSBuKCkpICU+JSAKICBzcHJlYWQoYXBwcm9hY2gsbl9ncmlkKSAlPiUgCiAgbXV0YXRlKGRpZmZlcmVuY2UgPXN0YXRlX3dhdGVycy1maXNoaW5nX3BvcnQsCiAgICAgICAgIHBlcmNlbnRhZ2Vfc3cgPSByb3VuZCgoZGlmZmVyZW5jZS9zdGF0ZV93YXRlcnMpKjEwMCkKICAgICAgICAgKQoKYGBgCgpBbmQgaGVyZSBpcyB0aGUgbWFwIHZpc3VhbGl6YXRpb24gb2YgdGhlIGNyb3BwZWQgZGlmZmVyZW5jZQoKYGBge3Igc3RhdGVfYmZfZGlmZl9tYXAsIGV2YWwgPSBULCBlY2hvID0gVH0KCmdyaWRfZWV6X3N3X2RmICU+JSAKICBtdXRhdGUoYXBwcm9hY2ggPSAic3RhdGVfd2F0ZXJzIikgJT4lIAogIGJpbmRfcm93cyhncmlkX2Vlel9mcF9kZikgJT4lCiAgbXV0YXRlKGFwcHJvYWNoID0gaWZlbHNlKGlzLm5hKGFwcHJvYWNoKSwiZmlzaGluZ19wb3J0IixhcHByb2FjaCkpICU+JSAKICBnZ3Bsb3QoKSArCiAgZ2VvbV90aWxlKAogICAgYWVzKAogICAgICB4ID0gbG9uLAogICAgICB5ID0gbGF0LAogICAgICBjb2xvciA9IGFwcHJvYWNoLAogICAgICBmaWxsID0gYXBwcm9hY2gKICAgICkKICApICsKICBmYWNldF93cmFwKH5zdGF0ZSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQyIikgKwogIHRoZW1lX2RhcmsoKQoKYGBgCgoKCiMjIyMgMy40IFBhcGVyIHBsb3Q7IEJ1ZmZlciBwbG90CgpgYGB7ciBjcm9wcGVkX3Bsb3RfcGFwZXIsIGV2YWwgPSBGLCBlY2hvID0gVH0KCiMjIyMgRGF0YSBuZWVkZWQgIyMjIwoKIyBHZXQgc3RhdGUgb3JkZXIgZnJvbSBOb3J0aCB0byBzb3V0aApzdGF0ZV9vcmRlciA8LSBteV9wYXRoKCJSIiwiUGFydGlhbC8iLCBuYW1lID0gImdyaWRfZWV6X2ZwX2RmLmNzdiIscmVhZCA9IFQpICU+JQogIGdyb3VwX2J5KHN0YXRlKSAlPiUgCiAgc3VtbWFyaXNlKAogICAgb3JkZXIgPSBtZWFuKGxhdCkKICApICU+JSAKICBtdXRhdGUoYWJyZXYgPSBjKCJDVCIsIkRFIiwiTUUiLCJNRCIsIk1BIiwiTkgiLCJOSiIsIk5ZIiwiTkMiLCJSSSIsIlZBIikKICApICU+JSAKICBhcnJhbmdlKGRlc2Mob3JkZXIpKSAlPiUgCiAgbXV0YXRlKG9yZGVyPSBjKCJiIiwiYSIsbGV0dGVyc1szOjExXSkpICMgd2VpcmRseSBtYWluZSBnb2VzIGJlbG93CgoKCiMgTG9hZCBncmlkIG9mIHN0YXRlIHdhdGVycwpncmlkX2Vlel9zd19zZiA8LSBzdF9yZWFkKG15X3BhdGgoIkQiLCJTcGF0aWFsL2dyaWRfZWV6X3N3X3NmIiwgbmFtZSA9ICJncmlkX2Vlel9zZi5zaHAiKSkgJT4lIAogIHNlbGVjdChpbmRleCxzdGF0ZSxnZW9tZXRyeSkgJT4lIAogIG11dGF0ZShtZXRob2QgPSAic3RhdGVfd2F0ZXJzIiwKICAgICAgICAgc3RhdGUgPSBzdHJfdG9fc2VudGVuY2Uoc3RhdGUpKSAlPiUgCiAgbGVmdF9qb2luKHN0YXRlX29yZGVyKQoKZ3JpZF9lZXpfc3dfc2YkZ3JvdXAgPC0gZmFjdG9yKGdyaWRfZWV6X3N3X3NmJGFicmV2LCAgICAgICMgUmVvcmRlcmluZyBncm91cCBmYWN0b3IgbGV2ZWxzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBzdGF0ZV9vcmRlciRhYnJldikKCgojIExvYWQgZ3JpZCBvZiBmaXNoaW5nIHBvcnRzCmdyaWRfZWV6X2ZwX3NmIDwtIHN0X3JlYWQobXlfcGF0aCgiRCIsIlNwYXRpYWwvZ3JpZF9lZXpfZnBfc2YiLCBuYW1lID0gImdyaWRfZWV6X2ZwLnNocCIpKSAlPiUgCiAgc2VsZWN0KGluZGV4LHN0YXRlID0ganVyc2RjdCxnZW9tZXRyeSkgJT4lIAogIG11dGF0ZShtZXRob2QgPSAiZmlzaGluZ19wb3J0IiwKICAgICAgICAgc3RhdGUgPSBzdHJfdG9fc2VudGVuY2Uoc3RhdGUpKSU+JSAKICBsZWZ0X2pvaW4oc3RhdGVfb3JkZXIpCgoKZ3JpZF9lZXpfZnBfc2YkZ3JvdXAgPC0gZmFjdG9yKGdyaWRfZWV6X2ZwX3NmJGFicmV2LCAgICAgICMgUmVvcmRlcmluZyBncm91cCBmYWN0b3IgbGV2ZWxzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBzdGF0ZV9vcmRlciRhYnJldikKCgojIFBsb3R0aW5nIAojIE1ha2Ugc3VyZSBzdF9zaW1wbGlmeSgpIGlzIHJ1biBmb3IgZWV6IHNmCgojIFN0YXRlIHdhdGVycyBwbG90CgpwX3N3IDwtIGdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKAogICMgT3ZlcmFsbCAob3ZlcmxhcHBpbmcpIHBvc2l0aW9uCiAgZ2dwbG90KGdyaWRfZWV6X3N3X3NmKSArCiAgICBnZW9tX3NmKGRhdGEgPSBlZXpfc2YsIGFlcygpLCBmaWxsID0gIndoaXRlIikgKyAKICAgIGdlb21fc2YoYWVzKGNvbG9yID1hYnJldiAsIGZpbGwgPSBhYnJldiksIGFscGhhID0gMC4zKSArCiAgICBnZW9tX3NmKGRhdGEgPSBsYW5kX3NmLCBhZXMoKSkgKwogICAgZ2dzZmxhYmVsOjpnZW9tX3NmX2xhYmVsX3JlcGVsKGRhdGEgPSBsYW5kX3NmLCBhZXMobGFiZWw9IGFicmV2KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYm94LnBhZGRpbmcgPSAwLjEwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHN0YXRlX3BhbGxldCkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSArCiAgICBteV9nZ3RoZW1lX3AobGVnX3BvcyA9ICIiLAogICAgICAgICAgICAgICAgIGF4X3R4X3MgPSAxMykgKwogICAgY29vcmRfc2YoeWxpbSA9IGMoMzAsNDgpKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygzMCwzNSw0MCw0NSkpKwogICAgbGFicyh4ID0gIiIsIHkgPSAiIiwgdGl0bGUgPSAiQSkgU3RhdGUgd2F0ZXJzIGV4dHJhcG9sYXRpb24iKSArCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCkpLAogICMgU2hvd2luZyBlYWNoIHN0YXRlIHNlcGFyYXRlbHkKICBnZ3Bsb3QoZ3JpZF9lZXpfc3dfc2YpICsKICAgIGdlb21fc2YoZGF0YSA9IGxhbmRfc2YsIGFlcygpLCBmaWxsID0gImdyZXk4MCIpICsKICAgIGdlb21fc2YoYWVzKGNvbG9yID0gYWJyZXYpLHNpemUgPSAwLjEsIGFscGhhID0gMC4zKSArCiAgICBmYWNldF93cmFwKH4gZ3JvdXApICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0LAogICAgICAgICAgICAgICAgICAgICAgICMgbGFiZWxzID0gdW5pcXVlKGdyaWRfZWV6X3N3X3NmJGdyb3VwKSkgKwogICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGdyaWRfZWV6X3N3X3NmICU+JSBhcnJhbmdlKG9yZGVyKSAlPiUgIHB1bGwoc3RhdGUpICU+JSB1bmlxdWUoKSkgKwogICAgZ2d0aXRsZSgiIikgKwogICAgbXlfZ2d0aGVtZV9wKGxlZ19wb3MgPSAiIiwKICAgICAgICAgICAgICAgICBheF90eF9zID0gMTEsCiAgICAgICAgICAgICAgICAgYXh4X3R4X2FuZyA9IDQ1LAogICAgICAgICAgICAgICAgIGhqdXN0ID0gMQogICAgKSwKICBucm93ID0gMSkKCgojIyMjIyAtLS0tLS0tLS0tLS0tICMjIyMKIyBGaXNoaW5nIFBvcnRzIHBsb3QKIyMjIyMgLS0tLS0tLS0tLS0tLSAjIyMjCgpwX2ZwIDwtIGdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKAogICMgT3ZlcmFsbCAob3ZlcmxhcHBpbmcpIHBvc2l0aW9uCiAgZ2dwbG90KGdyaWRfZWV6X2ZwX3NmKSArCiAgICBnZW9tX3NmKGRhdGEgPSBlZXpfc2YsIGFlcygpLCBmaWxsID0gIndoaXRlIikgKyAKICAgIGdlb21fc2YoYWVzKGNvbG9yID0gYWJyZXYsIGZpbGwgPSBhYnJldiksIGFscGhhID0gMC4zKSArCiAgICBnZW9tX3NmKGRhdGEgPSBsYW5kX3NmLCBhZXMoKSkgKwogICAgZ2dzZmxhYmVsOjpnZW9tX3NmX2xhYmVsX3JlcGVsKGRhdGEgPSBsYW5kX3NmLCBhZXMobGFiZWw9IGFicmV2KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYm94LnBhZGRpbmcgPSAwLjEwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHN0YXRlX3BhbGxldCkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gc3RhdGVfcGFsbGV0KSArCiAgICBteV9nZ3RoZW1lX3AobGVnX3BvcyA9ICIiLAogICAgICAgICAgICAgICAgIGF4X3R4X3MgPSAxMykgKwogICAgY29vcmRfc2YoeWxpbSA9IGMoMzAsNDgpKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygzMCwzNSw0MCw0NSkpICsKICAgIGxhYnMoeCA9ICIiLCB5ID0gIiIsIHRpdGxlID0gIkIpIEZpc2hpbmcgcG9ydHMgZXh0cmFwb2xhdGlvbiIpICsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSksCiAgIyBTaG93aW5nIGVhY2ggc3RhdGUgc2VwYXJhdGVseQogIGdncGxvdChncmlkX2Vlel9mcF9zZikgKwogICAgZ2VvbV9zZihkYXRhID0gbGFuZF9zZiwgYWVzKCksIGZpbGwgPSAiZ3JleTgwIikgKwogICAgZ2VvbV9zZihhZXMoY29sb3IgPSBhYnJldiksc2l6ZSA9IDAuMSwgYWxwaGEgPSAwLjMpICsKICAgIGZhY2V0X3dyYXAofiBncm91cCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQsCiAgICAgICAgICAgICAgICAgICAgICAgIyBsYWJlbHMgPSB1bmlxdWUoZ3JpZF9lZXpfZnBfc2YkZ3JvdXApKSArCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gZ3JpZF9lZXpfZnBfc2YgJT4lIGFycmFuZ2Uob3JkZXIpICU+JSAgcHVsbChzdGF0ZSkgJT4lIHVuaXF1ZSgpKSArCiAgICBnZ3RpdGxlKCIiKSArCiAgICBteV9nZ3RoZW1lX3AobGVnX3BvcyA9ICIiLAogICAgICAgICAgICAgICAgIGF4X3R4X3MgPSAxMSwKICAgICAgICAgICAgICAgICBheHhfdHhfYW5nID0gNDUsCiAgICAgICAgICAgICAgICAgaGp1c3QgPSAxCiAgICApLAogIG5yb3cgPSAxKQoKCgpjb21iaW5lZF9wbG90IDwtIGdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKHBfc3cscF9mcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBib3R0b20gPSAiTG9uZ2l0dWRlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWZ0ID0gIkxhdGl0dWRlIikKCmdnc2F2ZShmaWxlbmFtZSA9ICJidWZmZXJfZmlndXJlX2IuanBnIiwKICAgICAgIHBsb3QgPSBjb21iaW5lZF9wbG90LAogICAgICAgcGF0aCA9IG15X3BhdGgoIlIiLCJGaWd1cmVzIiksCiAgICAgICB3aWR0aCA9IDExLAogICAgICAgaGVpZ2h0ID0gMTEKKQoKYGBgCgohW0J1ZmZlciBmaWd1cmUgZm9yIHBhcGVyXSgvVm9sdW1lcy9FbnRlcnByaXNlL0RhdGEvQWNyb3NzQm91bmRhcmllcy9SZXN1bHRzL0ZpZ3VyZXMvYnVmZmVyX2ZpZ3VyZV9iLmpwZykKCgpgYGB7ciByZW1vdmVfcGVuLCBldmFsID0gRiwgZWNobyA9IEZ9CgojIyMjX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18jIyMgCiMgU29sdmluZyBmb3IgSXNzdWUgIzggUGVubnN5bHZhbmlhIGhhcyBOTyBjb2FzdAojIyMjX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18jIyMgCgojIFJlbW92ZSBQZW5uc3lsdmFuaWEgZnJvbSBzZgpncmlkX2Vlel9zZiA8LSAgc3RfcmVhZCgiL1ZvbHVtZXMvRW50ZXJwcmlzZS9EYXRhL0Fjcm9zc0JvdW5kYXJpZXMvRGF0YS9TcGF0aWFsL2dyaWRfc2YvZ3JpZF9lZXpfc2Yuc2hwIikgJT4lCiAgZmlsdGVyKHN0YXRlICE9ICJwZW5uc3lsdmFuaWEiKQoKIyBNYWtlIHN1cmUgbm8gUGVubi4KdW5pcXVlKGdyaWRfZWV6X3NmJHN0YXRlKQoKIyBvdmVyIHdyaXRlIHNmCndyaXRlX3NmKGdyaWRfZWV6X3NmLCBwYXN0ZTAobXlfcGF0aCgiRCIsICJTcGF0aWFsIiksImdyaWRfZWV6X3NmLnNocCIpKQoKI01ha2Ugc3VyZSBvZiB0aGluZ3MKCiMgZ3JpZF9lZXpfc2YgPC0gIHN0X3JlYWQoIi9Wb2x1bWVzL0VudGVycHJpc2UvRGF0YS9BY3Jvc3NCb3VuZGFyaWVzL0RhdGEvU3BhdGlhbC9ncmlkX3NmL2dyaWRfZWV6X3NmLnNocCIpCgojIHVuaXF1ZShncmlkX2Vlel9zZiRzdGF0ZSkKCiMgTm93IHNhdmUgaXQgYXMgYSBERiB0b28KCiMgZ3JpZF9lZXpfZGYgPC0gYXMuZGF0YS5mcmFtZShncmlkX2Vlel9zZikgJT4lCiAgIyBzZWxlY3Qoc3RhdGUsaW5kZXgpICU+JQogICMgbGVmdF9qb2luKG5lX2dyaWQsCiAgICAgICAgICAgICMgYnkgPSAiaW5kZXgiKQoKIyB3cml0ZV9jc3YoZ3JpZF9lZXpfZGYsIHBhc3RlMChteV9wYXRoKCJSIiwgIlBhcnRpYWwiKSwiZ3JpZF9lZXpfZGYuY3N2IikpCmBgYAoKCiMjIyBJbnRlcnBvbGF0aW9uIHJ1dGluZQoKSW4gdGhpcyBzdGVwIHdlIFtpbnRlcnBvbGF0ZV0oaHR0cHM6Ly9zd2lsa2UtZ2Vvc2NpZW5jZS5uZXQvcG9zdC9zcGF0aWFsX2ludGVycG9sYXRpb24vKSB0aGUgc3VydmV5IGRhdGEgd2l0aGluIHRoZSBwcmV2aW91c2x5IGNyZWF0ZWQgZ3JpZCBmb2xsb3dpbmcgYSBUcmlhbmd1bGFyIElycmVndWxhciBTdXJmYWNlIG1ldGhvZC4KCi0gV2UgcmVtb3ZlZCBjYXNlcyB3aGVyZSBgd3RjcHVlIDwgMGAKCiMjIyMgRnVuY3Rpb25zIG5lZWRlZAoKV2UgbmVlZCB0byBjcmVhdGUgYSBjb3VwbGUgb2YgZnVuY3Rpb25zIHRvIHJ1biB0aGUgd2hvbGUgcHJvY2VzcwoKIyMjIyMgSW50ZXJwb2xhdGlvbiBtYWluIGZ4ICh0aXMpLgoKVGhpcyBpcyB0aGUgbWFpbiBmdW5jdGlvbiB1c2VkIHRvIGludGVycG9sYXRlIHRoZSBkYXRhIHBlciB5ZWFyLiBJdCBmb2xsb3dzIGEgVHJpYW5ndWxhciBJcnJlZ3VsYXIgU3VyZmFjZSBtZXRob2QgdXNpbmcgdGhlIGBpbnRlcnA6OmludGVycCgpYCBmdW5jdGlvbi4gSWYgeW91IHdhbnQgdG8gc2VlIHRoZSBmdW5jdGlvbiBjbGljIG9uIGBjb2RlYAoKYGBge3IgaW50ZXJwb2xfZnVuY3Rpb24sIGV2YWwgPSBULCBlY2hvID0gVH0KCnRpcyA8LSBmdW5jdGlvbihpbnB1dF9kYXRhLCBncmlkLCB5ciwgdGF4YSwgcmVnKXsKICAKICAjIC0tLS0tLS0tLS0tLS0tLSAjCiAgIyBUZXN0aW5nCiAgIyBwcmludChwYXN0ZSh5cikpCiAgIyB5ciA9IDE5NzYKICAjIC0tLS0tLS0tLS0tLS0tLSAjCiAgCiAgIyBGaWx0ZXIgZGF0YQogIGRhdGEgPC0gaW5wdXRfZGF0YSAlPiUgCiAgICBmaWx0ZXIoeWVhciA9PSB5ciwKICAgICAgICAgICBzcHAgPT0gdGF4YSwKICAgICAgICAgICByZWdpb24gPT0gcmVnCiAgICApICU+JSAKICAgICMgQXZlcmFnZSBkdXBsaWNhdGVkIGhhdWxzIGluIHRoZSBzYW1lIHNwb3QKICAgIGdyb3VwX2J5KHJlZ2lvbix5ZWFyLHNwcCxsYXQsbG9uKSAlPiUKICAgIHN1bW1hcmlzZV9hdCh2YXJzKHd0Y3B1ZSksCiAgICAgICAgICAgICAgICAgbWVhbixuYS5ybSA9IFQpCiAgICAKICAjIE9ubHkgaW50ZXJwb2xhdGUgY2FzZXMgd2hlcmUgdGhlcmUgaXMgbW9yZSB0aGFuIDMgcm93cwogICMgTWFya2VkIGJ5IHRoZSBmdW5jdGlvbiAKICAgIGlmKG5yb3coZGF0YSkgPD0gMyl7CiAgICAgIGZpdF90aW4gPC0gdGliYmxlKCkKICAgIH1lbHNlewogICAgICAKICAgICAgIyBUcmlhbmd1bGFyIElycmVndWxhciBTdXJmYWNlCiAgICAgIGZpdF90aW4gPC0gaW50ZXJwOjppbnRlcnAoICMgdXNpbmcge2ludGVycH0KICAgICAgICB4ID0gZGF0YSRsb24sICAgICAgICAgICAjIHRoZSBmdW5jdGlvbiBhY3R1YWxseSBhY2NlcHRzIGNvb3JkaW5hdGUgdmVjdG9ycwogICAgICAgIHkgPSBkYXRhJGxhdCwKICAgICAgICB6ID0gZGF0YSR3dGNwdWUsCiAgICAgICAgeG8gPSBncmlkJGxvbiwgICAgICMgaGVyZSB3ZSBhbHJlYWR5IGRlZmluZSB0aGUgdGFyZ2V0IGdyaWQKICAgICAgICB5byA9IGdyaWQkbGF0LAogICAgICAgIG91dHB1dCA9ICJwb2ludHMiCiAgICAgICkgJT4lIAogICAgICAgIGJpbmRfY29scygpICU+JSAKICAgICAgICBiaW5kX2NvbHMoZ3JpZCkgJT4lCiAgICAgICAgbXV0YXRlKHllYXIgPSB5ciwKICAgICAgICAgICAgICAgcmVnaW9uID0gcmVnLAogICAgICAgICAgICAgICBzcHAgPSB0YXhhKSAlPiUgCiAgICAgICAgc2VsZWN0KGluZGV4LCBzdGF0ZSwgeWVhciwgcmVnaW9uLCBzcHAsIGxvbj14LCBsYXQ9eSwgdmFsdWUgPSB6KQogICAgICAKICAgIH0KICAgCiAgICByZXR1cm4oZml0X3RpbikKfQoKIyBUZXN0IG1lCiMgTmVlZHMgdmFyaWFibGVzIGluIENvbnRyb2wgcGFuZWwKIyBUZXN0IG5vIGRhdGE6ICJBbG9zYSBhZXN0aXZhbGlzIiwgcmVnID0gIk5vcnRoZWFzdCBVUyBGYWxsIiwgeXIgPSAxOTc0IAojIHRpcyhpbnB1dF9kYXRhID0gb2NlYW5fZGF0YSwgZ3JpZCA9IGdyaWRfZWV6X2RmLCB0YXhhID0gIklsbGV4IGlsbGVjZWJyb3N1cyIsIHJlZyA9ICJOb3J0aGVhc3QgVVMgRmFsbCIsIHlyID0gMTk3MykKCgoKIyBsYXBwbHkoeWVhcnMsdGlzLGlucHV0X2RhdGEgPSBvY2Vhbl9kYXRhLCBncmlkID0gZ3JpZF9lZXpfZGYsIHRheGEgPSAiSWxsZXggaWxsZWNlYnJvc3VzIiwgcmVnID0gcmVnaW9uc1syXSkKCmBgYAoKIyMjIyMgUnVuIGZ1bmN0aW9uCgpUaGlzIGlzIGEgc3ViLWZ1bmN0aW9uIHRoYXQgcnVucyB0aGUgYHRpcygpYCBmdW5jdGlvbiBieSB0YXhhIGFuZCByZWdpb24uIEl0IHNhdmVzIHRoZSBvdXRwdXQgYXMgYSAuY3N2IGZpbGUgZm9yIGVhY2ggc3BlY2llcy4gCgpgYGB7ciBpbnRlcnBvbF9ydW5fZnVuLCBldmFsID0gVCwgZWNobyA9IFR9CgoKcnVuX3RpcyA8LSBmdW5jdGlvbihpbnB1dF9kYXRhLCBncmlkLCB5ZWFycywgdGF4YSwgcmVnLCBtZXRob2QpewogIAogIAogICMgUnVuIHRpcyBmb3Igc3BlY2llcyBhbmQgc3VydmV5cwogIGZvcihyIGluIDE6Mil7CiAgICAKICAgIHBhcnRpYWxfZGYgPC0gYmluZF9yb3dzKAogICAgICBsYXBwbHkoeWVhcnMsdGlzLGlucHV0X2RhdGEgPSBpbnB1dF9kYXRhLCBncmlkID0gZ3JpZCwgdGF4YSA9IHRheGEsIHJlZyA9IHJlZ1tyXSkKICAgICkKICAgIAogICAgaWYociA9PSAxKXsKICAgICAgaGlzdG9yaWNfdGlmIDwtIHBhcnRpYWxfZGYKICAgIH1lbHNlewogICAgICBoaXN0b3JpY190aWYgPC0gYmluZF9yb3dzKGhpc3RvcmljX3RpZixwYXJ0aWFsX2RmKQogICAgfQogICAgCiAgfQogIAogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIwogICMgU2F2ZSBkYXRhc2V0IHBlciBzcGVjaWVzCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAjCiAgCiAgIyBTZXQgZmlsZSBuYW1lCiAgbmFtZSA8LSBwYXN0ZTAoInRpZl8iLHN0cl9yZXBsYWNlKHRheGEsIiAiLCJfIiksIi5jc3YiKQogIAogIGNvbXBsZW1lbnQgPC0gcGFzdGUwKCJQYXJ0aWFsL0ludGVycG9sYXRpb24vIixtZXRob2QpCiAgCiAgIyBTZXQgcGF0aCBuYW1lCiAgc2F2ZV9wYXRoIDwtIG15X3BhdGgoIlIiLGNvbXBsZW1lbnQpCiAgCiAgIyBTZXQgY29tcGxldGUgcGF0aAogIHNhdmVfbmFtZSA8LSBwYXN0ZTAoc2F2ZV9wYXRoLG5hbWUpCiAgCiAgIyBDcmVhdGUgZm9sZGVyIGlmIGl0IGRvZXMgbm90IGV4aXN0CiAgaWYoZmlsZS5leGlzdHMoc2F2ZV9wYXRoKSA9PSBGKXsKICAgIGRpci5jcmVhdGUoc2F2ZV9wYXRoKQogIH0KICAKICAjICBTYXZlIGZpbGUKICB3cml0ZV9jc3YoaGlzdG9yaWNfdGlmLHNhdmVfbmFtZSkKICAKICByZXR1cm5fbXNnIDwtIHBhc3RlKCJJbnRlcnBvbGF0aW9uIGRvbmUgZm9yIiwgdGF4YSkKICAKICByZXR1cm4ocmV0dXJuX21zZykKICAKICAKfQoKIyBUZXN0IG1lCiAgICAjIHJ1bl90aXMoaW5wdXRfZGF0YSA9IG9jZWFuX2RhdGEsIGdyaWQgPSBncmlkX2Vlel9mcF9kZiwgdGF4YSA9ICJDZW50cm9wcmlzdGlzIHN0cmlhdGEiLCB5ZWFycyA9IHNlcSgxOTcwLDE5ODApLCByZWcgPSByZWdpb25zLCBtZXRob2QgPSAidGVzdGEiKQoKYGBgCgoKIyMjIyBTdXJ2ZXkgZGF0YQoKVGhlIGludGVycG9sYXRpb24gd2FzIGRvbmUgd2l0aCBOT0FBIE5vcnRoZWFzdCBGaXNoZXJpZXMgU2NpZW5jZSBDZW50ZXIgU3ByaW5nIGFuZCBGYWxsIEJvdHRvbSBUcmF3bCBTdXJ2ZXlzIFtkYXRhXShodHRwczovL3d3dy5maXNoZXJpZXMubm9hYS5nb3YvcmVnaW9uL25ldy1lbmdsYW5kLW1pZC1hdGxhbnRpYyNzY2llbmNlKSBwcm92aWRlZCBieSBbT2NlYW4gYWRhcHRdKGh0dHBzOi8vb2NlYW5hZGFwdC5ydXRnZXJzLmVkdS8pLiBEYXRhIHdhcyBhY2Nlc3NlZCB0cm91Z2ggdGhlIFtHaXRodWJdKGh0dHBzOi8vZ2l0aHViLmNvbS9waW5za3lsYWIvT2NlYW5BZGFwdCkuCgoqSW4gcHJpbWFyeSBwdWJsaWNhdGlvbnMgdXNpbmcgZGF0YSBmcm9tIHRoZSBkYXRhYmFzZSwgcGxlYXNlIGNpdGUgUGluc2t5IGV0IGFsLiAyMDEzLiBNYXJpbmUgdGF4YSB0cmFjayBsb2NhbCBjbGltYXRlIHZlbG9jaXRpZXMuIFNjaWVuY2UgMzQxOiAxMjM5LTEyNDIgZG9pOiAxMC4xMTI2L3NjaWVuY2UuMTIzOTM1MiwgYXMgd2VsbCBhcyB0aGUgb3JpZ2luYWwgZGF0YSBzb3VyY2VzLioKCi0gVXNpbmcgb25seSB0aGUgTm9ydGhlYXN0IFVTIEZhbGwgYW5kIFNwcmluZyBib3R0b20gdHJhd2wgc3VydmV5IGRhdGEgZm9yIG5vdwoKIyMjIyMgU3BsaXR0aW5nIHVwIGRhdGEKCi0gTm8gcGFydCBvbiBzcGF0aWFsIGFuYWx5c2lzLiBDYW4gYmUgaWdub3JlZC4gCgpUaGlzIGlzIGp1c3QgYSBzdWItc3RlcCB0byBzcGxpdCB1cCB0aGUgZGF0YSBpbnRvIHNpbmdsZSBzcGVjaWVzIGZpbGVzLiBUaGlzIG1ha2VzIHRoZSBhcHAgZmFzdGVyIGFzIGl0IG9ubHkgbmVlZHMgdG8gbG9hZCBzcGVjaWVzIHNwZWNpZmljIGRhdGEsIHJhdGhlciB0aGFuIGFsbCB0aGUgZGF0YSBhdCBkZSBiZWdpbm5pbmcuIAoKYGBge3IgZGF0X2V4cGxvZGVkLCBldmFsID0gRiwgZWNobyA9IEYsIGZpZy53aWR0aCA9IDl9CgpvY2Vhbl9kYXRhIDwtIHJlYWRSRFMoIi9Wb2x1bWVzL0VudGVycHJpc2UvRGF0YS9waW5za3lsYWItT2NlYW5BZGFwdC05NjZhZGYwL2RhdGFfY2xlYW4vZGF0X2V4cGxvZGVkLnJkcyIpICMlPiUgCiAgIyBmaWx0ZXIoc3BwID09ICJDZW50cm9wcmlzdGlzIHN0cmlhdGEiLAogICAgICAgIyByZWdpb24gJWluJSBjKCJOb3J0aGVhc3QgVVMgRmFsbCIgLCAiTm9ydGhlYXN0IFVTIFNwcmluZyIpKSAjTm8gbW9yZSBzZWFzb25zCgoKc3BwX2RhdGEgPC0gZnVuY3Rpb24oc3BwKXsKICAKICBuYW1lX3NhdmUgPC0gcGFzdGUwKG15X3BhdGgoIkQiLCJTcHAvT2JzZXJ2YXRpb24iKSwib2JzXyIsc3RyX3JlcGxhY2Uoc3BwWzFdLCAiICIsICJfIiksIi5jc3YiKQoKb2NlYW5fZGF0YSAlPiUgCiAgZmlsdGVyKHNwcCA9PSBzcHAsCiAgICAgICByZWdpb24gJWluJSBjKCJOb3J0aGVhc3QgVVMgRmFsbCIgLCAiTm9ydGhlYXN0IFVTIFNwcmluZyIpCiAgICAgICApICU+JSAKICB3cml0ZV9jc3YoLiwgbmFtZV9zYXZlKQogIAp9CgpzcHBfbGlzdCA8LSBvY2Vhbl9kYXRhICU+JSAKICBmaWx0ZXIocmVnaW9uICVpbiUgcmVnaW9ucywKICAgICAgICAgc3BwICE9ICJOQSIpICU+JSAKICBwdWxsKHNwcCkgJT4lIAogIHVuaXF1ZSgpCiAgCgpsYXBwbHkoc3BwX2xpc3QsIHNwcF9kYXRhKQoKCnN1YnNldF9kYXRhIDwtIG9jZWFuX2RhdGEgJT4lIAogIGZpbHRlcihzcHAgPT0gIkNlbnRyb3ByaXN0aXMgc3RyaWF0YSIsCiAgICAgICByZWdpb24gJWluJSBjKCJOb3J0aGVhc3QgVVMgRmFsbCIgLCAiTm9ydGhlYXN0IFVTIFNwcmluZyIpCiAgICAgICApCgpnZ3Bsb3QoKSArCiAgZ2VvbV9wb2ludChkYXRhID0gc3Vic2V0KHN1YnNldF9kYXRhLCB3dGNwdWUgPSAwLjApLAogICAgICAgICAgICAgYWVzKAogICAgICAgICAgICAgICB4ID0gbG9uLAogICAgICAgICAgICAgICB5ID0gbGF0CiAgICAgICAgICAgICApLAogICAgICAgICAgICAgY29sb3IgPSAiZ3JleTk1IgogICkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHN1YnNldChzdWJzZXRfZGF0YSwgd3RjcHVlID4gMCksCiAgICAgICAgICAgICBhZXMoCiAgICAgICAgICAgICAgIHggPSBsb24sCiAgICAgICAgICAgICAgIHkgPSBsYXQsCiAgICAgICAgICAgICAgIGNvbG9yID0gbG9nMTAod3RjcHVlKQogICAgICAgICAgICAgKSwKICAgICAgICAgICAgIHNpemUgPSAxCiAgKSArCiAgc2NhbGVfY29sb3JfZGlzdGlsbGVyKHBhbGV0dGUgPSAiU3BlY3RyYWwiLCAKICAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGVfbGVnZW5kKHRpdGxlID0gIldDUFVFIHBlciBIYXVsIChsb2cxMCkiKSkgKyAKICBjb29yZF9zZih4bGltID0gYygtNzYsIC02NSkseWxpbSA9IGMoMzUsIDQ1KSkgKwogIE15RnVuY3Rpb25zOjpteV9nZ3RoZW1lX20oKSArCiAgZmFjZXRfd3JhcCh+cmVnaW9uKQoKYGBgCgojIyMjIENvbnRyb2wgUGFubmVsCgpUaGlzIGlzIHdoZXJlIHdlIGxvYWQgdGhlIHJlcXVpcmVkIGRhdGEgYW5kIHByZXBhcmUgdG8gcnVuIHRoZSBpbnRlcnBvbGF0aW9uIGZ1bmN0aW9uLiBOb3RlIHRoYXQgc29tZSBvZiB0aGUgZGF0YSBoZXJlIGhhcyBiZWVuIHByZXZpb3VzbHkgY3JlYXRlZCAKCmBgYHtyIGNvbnRyb19wYW5uZWwsIGV2YWwgPSBULCBlY2hvID0gVH0KCiMgTG9hZCBncmlkIGRmCiMgRm9yIGZpc2hpbmcgcG9ydHMKZ3JpZF9lZXpfZnBfZGYgPC0gbXlfcGF0aCgiRCIsIlNwYXRpYWwvZ3JpZF9lZXpfZnBfc2YiLCJncmlkX2Vlel9mcF9kZi5jc3YiLCByZWFkID0gVCkKCiMgRm9yIHN0YXRlIHdhdGVycwojIGdyaWRfZWV6X3N3X2RmIDwtIG15X3BhdGgoIkQiLCJTcGF0aWFsL2dyaWRfZWV6X2ZwX3NmIiwiZ3JpZF9lZXpfZnBfZGYuY3N2IiwgcmVhZCA9IFQpCgojIFJ1biBpbnRlcnBvbGF0aW9uIGZvciBhbGwgeWVhcnMKeWVhcnMgPC0gc2VxKDE5NzMsMjAxOSwxKQoKIyByZWdpb25zCnJlZ2lvbnMgPC0gYygiTm9ydGhlYXN0IFVTIEZhbGwiICwgIk5vcnRoZWFzdCBVUyBTcHJpbmciKQoKIyBzcGVjaWVzIGxpc3QKc3BwIDwtIG9jZWFuX2RhdGEgJT4lIAogIGZpbHRlcihyZWdpb24gJWluJSByZWdpb25zLAogICAgICAgICBzcHAgIT0gIk5BIikgJT4lIAogIHB1bGwoc3BwKSAlPiUgCiAgdW5pcXVlKCkKCgojIERvdWJsZSBjaGVjayBydW5zCgpzcHBfcnVucyA8LSB0aWJibGUodGF4YSA9IChsaXN0LmZpbGVzKG15X3BhdGgoIlIiLCJQYXJ0aWFsL0ludGVycG9sYXRpb24vZnAiKSkpKSAlPiUKICBtdXRhdGUoCiAgICB0YXhhID0gc3RyX3JlbW92ZSh0YXhhLCAidGlmXyIpLAogICAgdGF4YSA9IHN0cl9yZW1vdmUodGF4YSwgIi5jc3YiKSwKICAgIHRheGEgPSBzdHJfcmVwbGFjZSh0YXhhLCAiXyIsICIgIikKICApIAoKIyBNaXNzaW5nIHJ1bnMKc3BwIDwtIHRpYmJsZSh0YXhhPXNwcCkgJT4lIAogIGFudGlfam9pbihzcHBfcnVucykgJT4lIAogIHB1bGwodGF4YSkKCgpgYGAKCiMjIyMgUnVuIHJvdXRpbmUKCkhlcmUgd2UganVzdCBydW4gdGhlIHJvdXRpbmUgZm9yIGVhY2ggb2YgdGhlIHNwZWNpZXMgcHJlc2VudCBpbiB0aGUgTm9ydGhlYXN0IFVTIEZhbGwgYW5kIFNwcmluZyBzdXJ2ZXlzIGJldHdlZW4gMTk3MyBhbmQgMjAxOS4gCgotIE5vdGUgdGhlcmUgYXJlIDQzIGlkZW50aWZpZWQgdGF4YQotIFNvbWUgdGF4YSBkbyBub3QgaGF2ZSBwcmVzZW5jZSBkYXRhIGluIHNvbWUgeWVhcnMKCmBgYHtyIHJ1bl9yb3V0aW5lLCBldmFsID0gVCwgZWNobyA9IFR9CgojICMgc2luZ2xlIHNwZWNpZXMgcnVuCiMgcnVuX3RpcyhpbnB1dF9kYXRhID0gb2NlYW5fZGF0YSwKIyAgICAgICAgIGdyaWQgPSBncmlkX2Vlel9mcF9kZiwKIyAgICAgICAgIHllYXJzID0geWVhcnMsCiMgICAgICAgICByZWcgPSByZWdpb25zLAojICAgICAgICAgdGF4YSA9ICJJbGxleCBpbGxlY2Vicm9zdXMiLAojICAgICAgICAgbWV0aG9kID0gImZwIgojICkKCgojIFJ1biB0aGVtIGFsbCBpbiBwYXJhbGxlbApsYXBwbHkoc3BwLAogICAgICAgcnVuX3RpcywgCiAgICAgICBpbnB1dF9kYXRhID0gb2NlYW5fZGF0YSwKICAgICAgIGdyaWQgPSBncmlkX2Vlel9mcF9kZiwKICAgICAgIHllYXJzID0geWVhcnMsCiAgICAgICByZWcgPSByZWdpb25zLAogICAgICAgbWV0aG9kID0gImZwIgopCgoKYGBgCgojIFJlc3VsdHMKClJlc3VsdHMgYXJlIG5vdyBmb3IgZWlnaHQgc3BlY2llcyBtYW5hZ2VkIHVuZGVyIE1pZC1BdGxhbnRpYyBDb3VuY2lsIE1hbmFnZW1lbnQgUGxhbnMgYWNjb3JkaW5nIHRvIFtOT0FBXShodHRwczovL3d3dy5maXNoZXJpZXMubm9hYS5nb3YvbmV3LWVuZ2xhbmQtbWlkLWF0bGFudGljL2NvbW1lcmNpYWwtZmlzaGluZy9uZXctZW5nbGFuZC1taWQtYXRsYW50aWMtZmlzaGVyeS1tYW5hZ2VtZW50LXBsYW5zKS4KCgoqU2NvbWJlciBzY29tYnJ1cyosICpQZXByaWx1cyB0cmlhY2FudGh1cyogKGJ1dHRlcmZpc2gpLCAqSWxsZXggaWxsZWNlYnJvc3VzKiAoc2hvcnRmaW4gc3F1aWQpLCAqUGFyYWxpY2h0aHlzIGRlbnRhdHVzKiAoc3VtbWVyIGZsb3VuZGVyKSwgKlN0ZW5vdG9tdXMgY2hyeXNvcHMqIChTY29vcCksICpDZW50cm9wcmlzdGlzIHN0cmlhdGEqIChibGFjayBzZWEgYmFzcyksICpQb21hdG9tdXMgc2FsdGF0cml4KiAoQmx1ZWZpc2gpLCAqTG9waG9sYXRpbHVzIGNoYW1hZWxlb250aWNlcHMqIChHb2xkZW4gdGlsZWZpc2gpLCAqQ2F1bG9sYXRpbHVzIG1pY3JvcHMqIChibHVlbGluZSB0aWxlZmlzaCkgYW5kICpDbHVwZWEgaGFyZW5ndXMqCgoKYGBge3IgbG9hZF9kYXRhLCBldmFsID0gVCwgZWNobyA9IFR9CgojIFNwZWNpZXMgZGF0YQoKIyBMb2FkIGludGVycG9sYXRlZCBkYXRhCiMgIkNlbnRyb3ByaXN0aXMgc3RyaWF0YSIKIyAKIyBoaXN0b3JpY190aWYgPC0gbXlfcGF0aCgiUiIsIlBhcnRpYWwvSW50ZXJwb2xhdGlvbiIsInRpZl9DZW50cm9wcmlzdGlzX3N0cmlhdGEuY3N2IiwgcmVhZCA9IFQpICU+JSAKIyAgIG11dGF0ZShzdGF0ZSA9IHN0cl90b19zZW50ZW5jZShzdGF0ZSkpCgoKIyBNdWx0aXBsZSBzcGVjaWVzCgojIE1hbmFnZWQgc3BlY2llcyBieSBNaWQtQXRsYW50aWMgQ291bmNpbCBNYW5hZ2VtZW50IFBsYW5zLCBhbmQgU3RhdGUgd2F0ZXJzCiMgaHR0cHM6Ly93d3cuZmlzaGVyaWVzLm5vYWEuZ292L25ldy1lbmdsYW5kLW1pZC1hdGxhbnRpYy9jb21tZXJjaWFsLWZpc2hpbmcvbmV3LWVuZ2xhbmQtbWlkLWF0bGFudGljLWZpc2hlcnktbWFuYWdlbWVudC1wbGFucwoKU3BlY2llcyA8LSBjKAogICMgIlNjb21iZXIgc2NvbWJydXMiLAogICMgIkRvcnl0ZXV0aGlzIChBbWVyaWdvKSBwZWFsZWlpIiwgI2xvbmdmaW4gc3F1aWQgV0UgRE9OVCBIQVZFIElUCiAgIyAiUGVwcmlsdXMgdHJpYWNhbnRodXMiLCAjIGJ1dHRlcmZpc2gKICAjICJJbGxleCBpbGxlY2Vicm9zdXMiLCAjc2hvcnRmaW4gc3F1aWQKICAiUGFyYWxpY2h0aHlzIGRlbnRhdHVzIiwgI3N1bW1lciBmbG91bmRlcgogICJTdGVub3RvbXVzIGNocnlzb3BzIiwgI1NjdXAiCiAgIkNlbnRyb3ByaXN0aXMgc3RyaWF0YSIjLCAjIGJsYWNrIHNlYSBiYXNzCiAgIyAiUG9tYXRvbXVzIHNhbHRhdHJpeCIsICMgQmx1ZWZpc2gKICAjICJMb3Bob2xhdGlsdXMgY2hhbWFlbGVvbnRpY2VwcyIsICNnb2xkZW4gdGlsZWZpc2gKICAjICJDYXVsb2xhdGlsdXMgbWljcm9wcyIsICNibHVlbGluZSB0aWxlZmlzaAogICMgIkNsdXBlYSBoYXJlbmd1cyIgIyBBdGxhbnRpYyBoZXJyaW5nIChKb2ludGx5IGluIFN0YXRlIGFuZCBGZWRlcmFsIFdhdGVycykKICApCgoKc3BwX3BhdGhzIDwtIGxpc3QuZmlsZXMobXlfcGF0aCgiUiIsZXh0cmFfcGF0aCA9ICJQYXJ0aWFsL0ludGVycG9sYXRpb24iKSkKCiMgU29tZSBnaWJpcmlzIGZvciBuYW1lcwp0YXhvbl9saXN0IDwtIGdzdWIoIl8iLCIgIixzcHBfcGF0aHMpCnRheG9uX2xpc3QgPC0gZ3N1YigidGlmICIsIiIsdGF4b25fbGlzdCkKdGF4b25fbGlzdCA8LSBnc3ViKCIuY3N2IiwiIix0YXhvbl9saXN0KQoKdGF4b25fbGlzdCA8LSB0YXhvbl9saXN0W3RheG9uX2xpc3QgJWluJSBTcGVjaWVzXQoKIyBOb3cgc2V0IGEgbGlzdCBvZiBmaWxlcyB0byByZWFkCnRheG9uX3JlYWQgPC0gcGFzdGUwKCJ0aWZfIix0YXhvbl9saXN0LCIuY3N2IikKdGF4b25fcmVhZCA8LSBnc3ViKCIgIiwiXyIsdGF4b25fcmVhZCkKCnRheG9uX3JlYWQgPC0gc3BwX3BhdGhzW3NwcF9wYXRocyAlaW4lIHRheG9uX3JlYWRdCgp0YXhvbl9yZWFkIDwtIHBhc3RlMChteV9wYXRoKCJSIixleHRyYV9wYXRoID0gIlBhcnRpYWwvSW50ZXJwb2xhdGlvbiIpLHRheG9uX3JlYWQpCgoKIyBMb2FkIGFsbCBzcCBpbiBvbmUgdGFibGUKaGlzdG9yaWNfc3BwX3N3IDwtIGJpbmRfcm93cyhsYXBwbHkodGF4b25fcmVhZCwgZnJlYWQpKSAlPiUgCiAgbXV0YXRlKHN0YXRlID0gc3RyX3RvX3NlbnRlbmNlKHN0YXRlKSkKCgp1bmlxdWUoaGlzdG9yaWNfc3BwJHNwcCkKCiMgU3BhdGlhbCBkYXRhClN0YXRlcyA8LSBjKCJtYWluZSIsICJuZXcgaGFtcHNoaXJlIiwgIm1hc3NhY2h1c2V0dHMiLCAiY29ubmVjdGljdXQiLCAicmhvZGUgaXNsYW5kIiwgIm5ldyB5b3JrIiwgIm5ldyBqZXJzZXkiLCAiZGVsYXdhcmUiLCAibWFyeWxhbmQiLCAidmlyZ2luaWEiLCAibm9ydGggY2Fyb2xpbmEiKSAKCiMgVVMgU3RhdGUgTWFwIChsYW5kKQpsYW5kX3NmIDwtIHN0X2FzX3NmKG1hcCgic3RhdGUiLCBwbG90ID0gRkFMU0UsIGZpbGwgPSBUUlVFKSkgJT4lIAogIGZpbHRlcihJRCAlaW4lIFN0YXRlcykgJT4lIAogIG11dGF0ZShhYnJldiA9IGMoIkNUIiwiREUiLCJNRSIsIk1EIiwiTUEiLCJOSCIsIk5KIiwiTlkiLCJOQyIsIlJJIiwiVkEiKSwKICAgICAgICAgc3RhdGUgPSBzdHJfdG9fc2VudGVuY2UoSUQpCiAgICAgICAgICkKCiMgUGVyaW9kcwpwZXJpb2RzIDwtdGliYmxlKAogIG9yZGVyID0gYyhyZXAoImEiLDEyKSwKICAgICAgICAgICAgcmVwKCJiIiwxMiksCiAgICAgICAgICAgIHJlcCgiYyIsMTIpLAogICAgICAgICAgICByZXAoImQiLDExKQogICksCiAgbGFiZWwgPSBjKHJlcCgiMTk3My0xOTg0IiwxMiksCiAgICAgICAgICAgIHJlcCgiMTk4NS0xOTk2IiwxMiksCiAgICAgICAgICAgIHJlcCgiMTk5Ny0yMDA4IiwxMiksCiAgICAgICAgICAgIHJlcCgiMjAwOS0yMDE5IiwxMSkKICApLAogIHllYXIgPSBjKHNlcSgxOTczLDE5ODQsMSksCiAgICAgICAgICAgc2VxKDE5ODUsMTk5NiwxKSwKICAgICAgICAgICBzZXEoMTk5NywyMDA4LDEpLAogICAgICAgICAgIHNlcSgyMDA5LDIwMTksMSkKICApCikKCgpzdGF0ZV9sYXQgPC0gaGlzdG9yaWNfc3BwICU+JQogIGdyb3VwX2J5KHN0YXRlKSAlPiUgCiAgc3VtbWFyaXNlKAogICAgb3JkZXIgPSBtZWFuKGxhdCkKICApICU+JSAKICBtdXRhdGUoYWJyZXYgPSBjKCJDVCIsIkRFIiwiTUUiLCJNRCIsIk1BIiwiTkgiLCJOSiIsIk5ZIiwiTkMiLCJSSSIsIlZBIikKICApICU+JSAKICBhcnJhbmdlKGRlc2Mob3JkZXIpKSAlPiUgCiAgbXV0YXRlKG9yZGVyPSBsZXR0ZXJzWzE6MTFdKQoKCgojIFN0YXRlIHBhbGxldAoKc3RhdGVfcGFsbGV0IDwtIGMod2VzX3BhbGV0dGUobiA9IDUsIG5hbWUgPSAiRGFyamVlbGluZzEiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdlc19wYWxldHRlKG4gPSA1LCBuYW1lID0gIkRhcmplZWxpbmcyIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHdlc19wYWxldHRlKG4gPSAyLCBuYW1lID0gIkdyYW5kQnVkYXBlc3QxIikKICAgICAgICAgICAgICAgICAgIiNGRDY0NjciCiAgICAgICAgICAgICAgICAgICkKCgoKIyBwcmludCBmb3Igbm90ZWJvb2sKaGVhZChoaXN0b3JpY19zcHApCmBgYAoKIyMgQXZlcmFnZSBwcm9wb3J0aW9uCgpUaGlzIG1hcCBzaG93cyB0aGUgYWdncmVnYXRlZCBleHRyYXBvbGF0ZWQgdmFsdWUgZnJvbSBhbGwgdGhyZWUgc3BlY2llcyBwZXIgU3RhdGUgYXZlcmFnZSBhY3Jvc3MgdGhlIHdob2xlIHN0dWR5IHBlcmlvZCB3aXRoaW4gZWFjaCBTdGF0ZSdzIHdhdGVyLgoKKk5vdGU6KiBUaGlzIGlzIGludGVuZGVkIHRvIGJlIGEgc3VwcGxlbWVudGFsIGZpZ3VyZQoKYGBge3IgYXJlYV9tYXBfc3RhdGUsIGV2YWwgPSBULCBlY2hvID0gVCwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTEyfQoKIGRhdGFfZ3JpZCA8LSBoaXN0b3JpY19zcHAgJT4lIAogIGdyb3VwX2J5KHN0YXRlLGxhdCxsb24scmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKHN1bSA9IHN1bSh2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAjIHN1bSBvZiBhbGwgc3BlY2llcwogIGdyb3VwX2J5KHN0YXRlLGxhdCxsb24scmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKHN1bSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICMgYXZlcmFnZSBvZiBhbGwgeWVhcnMKCgpnZ3Bsb3QoZGF0YSA9IHN1YnNldChkYXRhX2dyaWQsICFpcy5uYShtZWFuKSkpICsKICBnZW9tX3RpbGUoCiAgICBhZXMoCiAgICAgIHggPSBsb24sCiAgICAgIHkgPSBsYXQsCiAgICAgIGZpbGwgPSBtZWFuLAogICAgICBjb2wgPSBtZWFuCiAgICApCiAgKSArCiAgZ2VvbV9zZihkYXRhID0gbGFuZF9zZiwgYWVzKCkpICsKICBmYWNldF93cmFwKH4gc3RhdGUgICsgIHJlZ2lvbiwKICAgICAgICAgICAgIG5jb2wgPSA0KSArCiAgbGFicyh4ID0gIkxvbmdpdHVkZSIsIHkgPSAiTGF0aXR1ZGUiKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzKCJNZWFuIEludGVycG9sYXRpb24iLCBhbHBoYSA9IDAuOCkgKwogIHNjYWxlX2NvbG9yX3ZpcmlkaXMoIk1lYW4gSW50ZXJwb2xhdGlvbiIsIGFscGhhID0gMC44KSArCiAgdGhlbWVfYncoKQpgYGAKCiMjIFByb3BvcnRpb24gQ2hhbmdlCgpIZXJlIHdlIHNob3cgdGhlIGF2ZXJhZ2UgcHJvcG9ydGlvbiBvZiB0aGUgaW50ZXJwb2xhdGlvbiBieSBTdGF0ZSBhbmQgdGltZSBwZXJpb2QuIFRpbWUgcGVyaW9kcyB3ZXJlIGFyYml0cmFyeSBkZWZpbmVkIGFzOwoKLSBFYXJseTsgMTk3MyB0byAxOTg0Ci0gTWlkOyAxOTg1IHRvIDE5OTcKLSBMYXRlOyAxOTk4IHRvIDIwMTEKLSBOb3c7IDIwMTIgdG8gMjAxOQoKKk5vdGVzOiogRmlndXJlIHJlcHJlc2VudHMgdGhlICoqU3ByaW5nKiogc3VydmV5LiBUaGlzIGNvbXB1dGF0aW9uIGNvbnNpZGVycyB0aGUgT3ZlcmxhcHBpbmcgb2Ygc3RhdGUgd2F0ZXJzLgoKIyMjIER5bmFtaWMgZmlndXJlOiBBZ2dyZWdhdGVkIFByb3BvcnRpb25hbCBjaGFuZ2UgcGVyIHN1cnZleQoKYGBge3IgYXJlYV9tYXBfYWdncmVnYXRlZCwgZXZhbCA9IFQsIGVjaG8gPSBULCBmaWcud2lkdGggPSAxMCwgZmlnLmhlaWdodD02fQoKdG90YWxfZml0ZWQgPC0gaGlzdG9yaWNfc3BwICU+JSAKICBncm91cF9ieSh5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZSh0b3RhbF92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT1UKSwuZ3JvdXBzID0gImRyb3AiKQoKCnN0YXRlX2ZpdCA8LSBoaXN0b3JpY19zcHAgJT4lIAogIGdyb3VwX2J5KHN0YXRlLHllYXIscmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKHN0YXRlX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPSBUKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lIAogIGxlZnRfam9pbih0b3RhbF9maXRlZCwKICAgICAgICAgICAgYnkgPSBjKCJ5ZWFyIiwicmVnaW9uIikpICU+JQogIG11dGF0ZShwZXJjZW50YWdlID0gc3RhdGVfdmFsdWUvdG90YWxfdmFsdWUqMTAwKSAlPiUgCiAgbGVmdF9qb2luKHBlcmlvZHMsCiAgICAgICAgICAgIGJ5ID0gInllYXIiKSAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUsb3JkZXIsbGFiZWwscmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fcGVyID0gcm91bmQobWVhbihwZXJjZW50YWdlKSksLmdyb3VwcyA9ICJkcm9wIikKCiMgY2hlY2sgcGVyY2VudGFnZXMKIyBzdGF0ZV9maXQgJT4lIAojICAgZ3JvdXBfYnkocGVyaW9kKSAlPiUgCiMgICBzdW1tYXJpc2Uoc3VtKG1lYW5fcGVyKSkKCgpwIDwtIGxhbmRfc2YgJT4lIAogIGxlZnRfam9pbihzdGF0ZV9maXQsCiAgICAgICAgICAgIGJ5ID0gInN0YXRlIikgJT4lIAogIGdncGxvdCgpICsKICAjIGdlb21fc2YoYWVzKGZpbGwgPSBtZWFuX3BlcikpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gbWVhbl9wZXIsIHRleHQgPSBwYXN0ZShzdGF0ZSwgbWVhbl9wZXIsIiUgb2YgcHJvcG9ydGlvbiIpKSkgKwogIHZpcmlkaXM6OnNjYWxlX2ZpbGxfdmlyaWRpcygiQXZlcmFnZSBwcm9wb3J0aW9uIHBlciBTdGF0ZSIsIGFscGhhID0gMC44KSArCiAgZmFjZXRfd3JhcCh+IHJlZ2lvbiArIGxhYmVsLCAKICAgICAgICAgICAgIG5yb3cgPSAyKSArCiAgbGFicyh4ID0gIkxhdGl0dWRlIiwgCiAgICAgICB5ID0gIkxvbmdpdHVkZSIpICsKICBteV9nZ3RoZW1lX3AoZmFjZXRfdHhfcyA9IDEyLAogICAgICAgICAgICAgICBsZWdfcG9zID0gImJvdHRvbSIpICsKICB0aGVtZShsZWdlbmQua2V5LndpZHRoID0gdW5pdCgxLCJsaW5lIikpICsKICB0aGVtZV9kYXJrKCkKCmdncGxvdGx5KHAsCiAgICAgICAgIHRvb2x0aXAgPSAidGV4dCIsCiAgICAgICAgIGR5bmFtaWNUaWNrcyA9IEZBTFNFKSAlPiUgCiAgICBzdHlsZShob3ZlcmxhYmVsID0gbGlzdChiZ2NvbG9yID0gIndoaXRlIiksIGhvdmVyb24gPSAiZmlsbCIpCgoKYGBgCgoKIyMjIFBhcGVyIGZpZ3VyZTsgUGVyIHNwZWNpZXMgbWFwcwoKYGBge3IgcGFwZXJfZmlndXJlX2FyZWFfbWFwLCBldmFsID0gRiwgZWNobyA9IFQsIHJlc3VsdHM9J2hpZGUnfQoKdG90YWxfZml0ZWQgPC0gaGlzdG9yaWNfc3BwICU+JSAKICBncm91cF9ieSh5ZWFyLHJlZ2lvbixzcHApICU+JSAKICBzdW1tYXJpc2UodG90YWxfdmFsdWUgPSBzdW0odmFsdWUsbmEucm09VCksLmdyb3VwcyA9ICJkcm9wIikKCgpzdGF0ZV9maXQgPC0gaGlzdG9yaWNfc3BwICU+JSAKICBncm91cF9ieShzdGF0ZSx5ZWFyLHJlZ2lvbixzcHApICU+JSAKICBzdW1tYXJpc2Uoc3RhdGVfdmFsdWUgPSBzdW0odmFsdWUsbmEucm09IFQpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUgCiAgbGVmdF9qb2luKHRvdGFsX2ZpdGVkLAogICAgICAgICAgICBieSA9IGMoInllYXIiLCJyZWdpb24iLCJzcHAiKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRhZ2UgPSBzdGF0ZV92YWx1ZS90b3RhbF92YWx1ZSoxMDApICU+JSAKICBsZWZ0X2pvaW4ocGVyaW9kcywKICAgICAgICAgICAgYnkgPSAieWVhciIpICU+JSAKICBncm91cF9ieShzdGF0ZSxvcmRlcixsYWJlbCxyZWdpb24sc3BwKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fcGVyID0gcm91bmQobWVhbihwZXJjZW50YWdlKSksLmdyb3VwcyA9ICJkcm9wIikgJT4lIAogICNPbmx5IHNob3cgcmVzdWx0cyBmb3Igc3ByaW5nCiAgZmlsdGVyKHN0cl9kZXRlY3QocmVnaW9uLCJTcHJpbmciKSkgJT4lIAogIG11dGF0ZShzcHAgPSBnc3ViKCIgIiwiXG4iLHNwcCkpCgojIFRoZSBwbG90Cm1hcF9wbG90IDwtIGxhbmRfc2YgJT4lIAogIGxlZnRfam9pbihzdGF0ZV9maXQsCiAgICAgICAgICAgIGJ5ID0gInN0YXRlIikgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gbWVhbl9wZXIpKSArCiAgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKCJBdmVyYWdlIHByb3BvcnRpb24gcGVyIFN0YXRlIiwgYWxwaGEgPSAwLjgpICsKICBmYWNldF9ncmlkKHNwcCB+IGxhYmVsKSArCiAgbGFicyh4ID0gIkxvbmdpdHVkZSIsIAogICAgICAgeSA9ICJMYXRpdHVkZSIpICsKICBteV9nZ3RoZW1lX3AoZmFjZXRfdHhfcyA9IDIwLAogICAgICAgICAgICAgICBsZWdfcG9zID0gImJvdHRvbSIsCiAgICAgICAgICAgICAgIGF4eF90eF9hbmcgPSA0NSwKICAgICAgICAgICAgICAgYXhfdHhfcyA9IDEyLAogICAgICAgICAgICAgICBheF90bF9zID0gMTgsCiAgICAgICAgICAgICAgIGhqdXN0ID0gMSkgKwogIHRoZW1lKGxlZ2VuZC5rZXkud2lkdGggPSB1bml0KDQsImxpbmUiKSkgCgoKICBnZ3NhdmUoZmlsZW5hbWUgPSAicHJvcG9ydGlvbl9jaGdfc3BwLmpwZyIsCiAgICAgICAgIHBsb3QgPSBtYXBfcGxvdCwKICAgICAgICAgcGF0aCA9IG15X3BhdGgoIlIiLCJGaWd1cmVzIiksCiAgICAgICAgIHdpZHRoID0gMTQsCiAgICAgICAgIGhlaWdodCA9IDE0CiAgICAgICAgICkKCgpgYGAKCgohW1Byb3BvcnRpb24gY2hhbmdlIHBlciBzcGVjaWVzIG1hcCBmb3IgcGFwZXJdKC9Wb2x1bWVzL0VudGVycHJpc2UvRGF0YS9BY3Jvc3NCb3VuZGFyaWVzL1Jlc3VsdHMvRmlndXJlcy9wcm9wb3J0aW9uX2NoZ19zcHAuanBnKQoKCiMjIyBQYXBlciBmaWd1cmU6IEFnZ3JlZ2F0ZWQgUHJvcG9ydGlvbmFsIGNoYW5nZQoKYGBge3IgYXJlYV9tYXBfYWdncmVnYXRlZF9mb3JtYW5zLCBldmFsID0gVCwgZWNobyA9IFQsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0PTZ9Cgp0b3RhbF9maXRlZCA8LSBoaXN0b3JpY19zcHAgJT4lIAogIGdyb3VwX2J5KHllYXIscmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKHRvdGFsX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPVQpLC5ncm91cHMgPSAiZHJvcCIpCgoKc3RhdGVfZml0IDwtIGhpc3RvcmljX3NwcCAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUseWVhcixyZWdpb24pICU+JSAKICBzdW1tYXJpc2Uoc3RhdGVfdmFsdWUgPSBzdW0odmFsdWUsbmEucm09IFQpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUgCiAgbGVmdF9qb2luKHRvdGFsX2ZpdGVkLAogICAgICAgICAgICBieSA9IGMoInllYXIiLCJyZWdpb24iKSkgJT4lCiAgbXV0YXRlKHBlcmNlbnRhZ2UgPSBzdGF0ZV92YWx1ZS90b3RhbF92YWx1ZSoxMDApICU+JSAKICBsZWZ0X2pvaW4ocGVyaW9kcywKICAgICAgICAgICAgYnkgPSAieWVhciIpICU+JSAKICBncm91cF9ieShzdGF0ZSxvcmRlcixsYWJlbCxyZWdpb24pICU+JSAKICBzdW1tYXJpc2UobWVhbl9wZXIgPSByb3VuZChtZWFuKHBlcmNlbnRhZ2UpKSwuZ3JvdXBzID0gImRyb3AiKSAlPiUgCiAgZmlsdGVyKHN0cl9kZXRlY3QocmVnaW9uLCJTcHJpbmciKSkKCgphZ2dfbWFwIDwtIGxhbmRfc2YgJT4lIAogIGxlZnRfam9pbihzdGF0ZV9maXQsCiAgICAgICAgICAgIGJ5ID0gInN0YXRlIikgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX3NmKGFlcyhmaWxsID0gbWVhbl9wZXIpKSArCiAgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKCJBdmVyYWdlIHByb3BvcnRpb24gcGVyIFN0YXRlIiwgYWxwaGEgPSAwLjgpICsKICBmYWNldF93cmFwKH4gbGFiZWwsIG5yb3cgPSAxKSArCiAgbGFicyh4ID0gIkxvbmdpdHVkZSIsIAogICAgICAgeSA9ICJMYXRpdHVkZSIpICsKICBteV9nZ3RoZW1lX3AoZmFjZXRfdHhfcyA9IDE2LAogICAgICAgICAgICAgICBsZWdfcG9zID0gImJvdHRvbSIsCiAgICAgICAgICAgICAgIGxlZ190bF9zID0gMTQsCiAgICAgICAgICAgICAgIGF4X3R4X3MgPSAxMCwKICAgICAgICAgICAgICAgYXhfdGxfcyA9IDE0KSArCiAgdGhlbWUobGVnZW5kLmtleS53aWR0aCA9IHVuaXQoMiwibGluZSIpKSAKCiAgZ2dzYXZlKGZpbGVuYW1lID0gInByb3BvcnRpb25fY2hnX2FnZy5qcGciLAogICAgICAgICBwbG90ID0gYWdnX21hcCwKICAgICAgICAgcGF0aCA9IG15X3BhdGgoIlIiLCJGaWd1cmVzIiksCiAgICAgICAgIHdpZHRoID0gOSwKICAgICAgICAgaGVpZ2h0ID0gNQogICAgICAgICApCgpgYGAKCiFbUHJvcG9ydGlvbiBjaGFuZ2UgYWdncmVnYXRlZCBhbGwgc3BlY2llcyBtYXAgZm9yIHBhcGVyXSgvVm9sdW1lcy9FbnRlcnByaXNlL0RhdGEvQWNyb3NzQm91bmRhcmllcy9SZXN1bHRzL0ZpZ3VyZXMvcHJvcG9ydGlvbl9jaGdfYWdnLmpwZykKCgojIyBBcmVhIHBsb3QKClRoaXMgZ3JhcGggc2hvd3MgdGhlIHByb3BvcnRpb24gb2YgdGhlIGludGVycG9sYXRpb24gdmFsdWUgZWFjaCBTdGF0ZSBoYXMgb3ZlciB0aW1lLgoKKk5vdGU6KiBUaGlzIHBsb3QgaXMgaW50ZXJhY3RpdmUuIEZvciBlYXNlIGNvbXBhcmlzb24gYmV0d2VlbiBTdGF0ZXMgeW91IGNhbjsKCi0gKk9uZSogY2xpY2sgb24gYW55IFN0YXRlIHRvICpyZW1vdmUqIGl0IGZyb20gdGhlIHBsb3QgCi0gKlR3byogY2xpY2tzIG9uIGFueSBTdGF0ZSB0byAqaXNvbGF0ZSBpdCogZnJvbSB0aGUgcGxvdCAob3RoZXIgc3RhdGVzIGNhbiB0aGVuIGJlIGFkZGVkIGJ5IGp1c3QgY2xpY2tpbmcgb24gdGhlbSkuCi0gVGhlIGJvdHRvbSBwYW5lbCBhbGxvd3MgeW91IHRvIHJlZHVjZSB0aGUgdGltZSBmcmFtZQoKIyMjIER5bmFtaWMgYWdncmVnYXRlZCBwbG90CgpgYGB7ciBkeW5hbWljX2FyZWFfcGxvdCwgZXZhbCA9IFQsIGVjaG8gPSBULCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQoKdG90YWxfZml0ZWQgPC0gaGlzdG9yaWNfc3BwICU+JSAKICBncm91cF9ieSh5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZSh0b3RhbF92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT1UKSwuZ3JvdXBzID0gImRyb3AiKQoKIyBncm91cCBieSBzdGF0ZQpzdGF0ZV9maXQgPC0gaGlzdG9yaWNfc3BwICU+JSAKICBncm91cF9ieShzdGF0ZSx5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZShzdGF0ZV92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBsZWZ0X2pvaW4odG90YWxfZml0ZWQsCiAgICAgICAgICAgIGJ5ID0gYygieWVhciIsInJlZ2lvbiIpKSAlPiUKICBtdXRhdGUocGVyY2VudGFnZSA9IHN0YXRlX3ZhbHVlL3RvdGFsX3ZhbHVlKjEwMCkKCiMgUGxvdCBtZQpwIDwtIGdncGxvdChzdGF0ZV9maXQpICsKICBnZW9tX2FyZWEoCiAgICBhZXMoCiAgICAgIHggPSB5ZWFyLAogICAgICB5ID0gcm91bmQocGVyY2VudGFnZSksCiAgICAgIGZpbGwgPSBzdGF0ZQogICAgKQogICkgKwogIHlsYWIoIlBlcmNlbnRhZ2UgKCUpIikgKwogICMgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVCwgYWxwaGEgPSAwLjgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQpICsKICBNeUZ1bmN0aW9uczo6bXlfZ2d0aGVtZV9wKCkgKwogIGZhY2V0X3dyYXAofnJlZ2lvbiwgbmNvbCA9IDEpICsKICB0aGVtZV9kYXJrKCkKCmdncGxvdGx5KHAsCiAgICAgICAgIGR5bmFtaWNUaWNrcyA9IFRSVUUpICU+JSAKICBsYXlvdXQoaG92ZXJtb2RlID0gIngiKSAlPiUKICByYW5nZXNsaWRlcigpCgpgYGAKCiMjIEFyZWEgcGxvdCAocnVubmluZyBtZWFuKQoKVGhpcyBncmFwaCBzaG93cyB0aGUgcHJvcG9ydGlvbiBvZiBlYWNoIFN0YXRlIHNtb290aGVkIG92ZXIgYSAqMTAgeWVhcnMgcnVubmluZyBtZWFuKiouIEl0IGFsbG93cyB0byBiZXR0ZXIgc2VlIGluY3JlYXNpbmcgYW5kIGRlY3JlYXNpbmcgdHJlbmRzLgoKIyMjIER5bmFtaWMgYWdncmVnYXRlZCBwbG90CgoqTm90ZToqIFRoaXMgcGxvdCBpcyBhbHNvIGludGVyYWN0aXZlIGFuZCB0aHVzLCBmb2xsb3dzIHRoZSBzYW1lIG9wdGlvbnMgb2YgdGhlIHByZXZpb3VzIG9uZS4KCmBgYHtyIGFyZWFfcGxvdCwgZXZhbCA9IFQsIGVjaG8gPSBULCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQoKIyBncm91cCBieSBzdGF0ZQpzdGF0ZV9maXQgPC0gaGlzdG9yaWNfc3BwICU+JSAKICBncm91cF9ieShzdGF0ZSx5ZWFyLHJlZ2lvbiwuZ3JvdXBzID0gImRyb3AiKSAlPiUgCiAgc3VtbWFyaXNlKHN0YXRlX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPSBUKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lIAogIGxlZnRfam9pbih0b3RhbF9maXRlZCwKICAgICAgICAgICAgYnkgPSBjKCJ5ZWFyIiwicmVnaW9uIikpICU+JQogIG11dGF0ZShwZXJjZW50YWdlID0gc3RhdGVfdmFsdWUvdG90YWxfdmFsdWUqMTAwKSAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUscmVnaW9uKSAlPiUgCiAgbXV0YXRlKFJNZWFuID0gem9vOjpyb2xsbWVhbih4ID0gcGVyY2VudGFnZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtPVQpCiAgICApICU+JSAgCiAgbGVmdF9qb2luKHN0YXRlX2xhdCkKCiMgUGxvdCBtZQpwIDwtIGdncGxvdChzdGF0ZV9maXQpICsKICBnZW9tX2FyZWEoCiAgICBhZXMoCiAgICAgIHggPSB5ZWFyLAogICAgICB5ID0gcm91bmQoUk1lYW4pLAogICAgICBmaWxsID0gc3RhdGUKICAgICAgIyBmaWxsID0gb3JkZXIKICAgICkKICApICsKICB5bGFiKCIxMCB5cnMgcnVubmluZyBhdmVyYWdlICglKSIpICsKICBzY2FsZV9maWxsX21hbnVhbCgKICAgICJTdGF0ZSIsCiAgICB2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQsCiAgICAjIGxhYmVscyA9IHN0YXRlX2ZpdCAlPiUgYXJyYW5nZShvcmRlcikgJT4lICBwdWxsKHN0YXRlKSAlPiUgdW5pcXVlKCkKICApICsKICBNeUZ1bmN0aW9uczo6bXlfZ2d0aGVtZV9wKCkgKwogIGZhY2V0X3dyYXAofnJlZ2lvbiwgbmNvbCA9IDEpICsKICB0aGVtZV9kYXJrKCkKCnN1cHByZXNzV2FybmluZ3MoCmdncGxvdGx5KHAsCiAgICAgICAgIGR5bmFtaWNUaWNrcyA9IFRSVUUpICU+JSAKICBsYXlvdXQoaG92ZXJtb2RlID0gIngiKSAlPiUgCiAgIyBhZGRfdHJhY2UoKSAlPiUgCiAgcmFuZ2VzbGlkZXIoKQopCgpgYGAKCiMjIyBQYXBlciBmaWd1cmU6IEFnZ3JlZ2F0ZWQgUHJvcG9ydGlvbmFsIGNoYW5nZQoKYGBge3IgcGxvdF9hcmVhX2F2ZV9hZ2csIGV2YWwgPSBGLCBlY2hvID0gRiwgcmVzdWx0cz0naGlkZSd9Cgp0b3RhbF9maXRlZCA8LSBoaXN0b3JpY19zcHAgJT4lIAogIGdyb3VwX2J5KHllYXIscmVnaW9uKSAlPiUgCiAgc3VtbWFyaXNlKHRvdGFsX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPVQpLC5ncm91cHMgPSAiZHJvcCIpCgoKIyBncm91cCBieSBzdGF0ZQpzdGF0ZV9maXQgPC0gaGlzdG9yaWNfc3BwICU+JSAKICBncm91cF9ieShzdGF0ZSx5ZWFyLHJlZ2lvbikgJT4lIAogIHN1bW1hcmlzZShzdGF0ZV92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBsZWZ0X2pvaW4odG90YWxfZml0ZWQsCiAgICAgICAgICAgIGJ5ID0gYygieWVhciIsInJlZ2lvbiIpKSAlPiUKICBtdXRhdGUocGVyY2VudGFnZSA9IHN0YXRlX3ZhbHVlL3RvdGFsX3ZhbHVlKjEwMCkgJT4lIAogIGdyb3VwX2J5KHN0YXRlLHJlZ2lvbikgJT4lIAogIG11dGF0ZShSTWVhbiA9IHpvbzo6cm9sbG1lYW4oeCA9IHBlcmNlbnRhZ2UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgMTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybT1UKQogICAgKSAlPiUgCiAgI09ubHkgc2hvdyByZXN1bHRzIGZvciBzcHJpbmcKICBmaWx0ZXIoc3RyX2RldGVjdChyZWdpb24sIlNwcmluZyIpLAogICAgICAgICAhaXMubmEoUk1lYW4pICMgUmVtb3ZlIE5BcyBmcm9tIHJvbGxtZWFuCiAgICAgICAgICkgJT4lICAKICBsZWZ0X2pvaW4oc3RhdGVfbGF0KQoKIyBQbG90IG1lCmFnZ19hcmVhIDwtIGdncGxvdChzdGF0ZV9maXQpICsKICBnZW9tX2FyZWEoCiAgICBhZXMoCiAgICAgIHggPSB5ZWFyLAogICAgICB5ID0gcm91bmQoUk1lYW4pLAogICAgICBmaWxsID0gb3JkZXIKICAgICAgIyBmaWxsID0gc3RhdGUKICAgICkKICApICsKICB5bGFiKCJQcm9wb3Rpb24gKDEwIHlycyBydW5uaW5nIGF2ZXJhZ2UpIikgKwogICMgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVCwgYWxwaGEgPSAwLjgpICsKICBzY2FsZV9maWxsX21hbnVhbCgKICAgICJTdGF0ZSIsCiAgICB2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQsCiAgICBsYWJlbHMgPSBzdGF0ZV9maXQgJT4lIGFycmFuZ2Uob3JkZXIpICU+JSAgcHVsbChzdGF0ZSkgJT4lIHVuaXF1ZSgpCiAgKSArCiAgbXlfZ2d0aGVtZV9wKGxlZ19wb3MgPSAicmlnaHQiKSArCiAgdGhlbWUobGVnZW5kLmtleS53aWR0aCA9IHVuaXQoMSwibGluZSIpKQoKCiAgZ2dzYXZlKGZpbGVuYW1lID0gImFyZWFfcGxvdF9hdmdfYWdnLmpwZyIsCiAgICAgICAgIHBsb3QgPSBhZ2dfYXJlYSwKICAgICAgICAgcGF0aCA9IG15X3BhdGgoIlIiLCJGaWd1cmVzIiksCiAgICAgICAgIHdpZHRoID0gOCwKICAgICAgICAgaGVpZ2h0ID0gNgogICkKCgpgYGAKCiFbUHJvcG9ydGlvbiBjaGFuZ2UgYWdncmVnYXRlZCBhbGwgc3BlY2llcyBtYXAgZm9yIHBhcGVyXSgvVm9sdW1lcy9FbnRlcnByaXNlL0RhdGEvQWNyb3NzQm91bmRhcmllcy9SZXN1bHRzL0ZpZ3VyZXMvYXJlYV9wbG90X2F2Z19hZ2cuanBnKQoKIyMjIFBhcGVyIGZpZ3VyZTogUGVyIFNwZWNpZXMgUHJvcG9ydGlvbmFsIGNoYW5nZQoKYGBge3IgcGFwZXJfcGxvdF9hcmVhX2F2ZV9zcHAsIGV2YWwgPSBGLCBlY2hvID0gRiwgcmVzdWx0cz0naGlkZSd9Cgp0b3RhbF9maXRlZCA8LSBoaXN0b3JpY19zcHAgJT4lIAogIGdyb3VwX2J5KHllYXIscmVnaW9uLHNwcCkgJT4lIAogIHN1bW1hcmlzZSh0b3RhbF92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT1UKSwuZ3JvdXBzID0gImRyb3AiKQoKCiMgZ3JvdXAgYnkgc3RhdGUKc3RhdGVfZml0IDwtIGhpc3RvcmljX3NwcCAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUseWVhcixyZWdpb24sc3BwKSAlPiUgCiAgc3VtbWFyaXNlKHN0YXRlX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPSBUKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lIAogIGxlZnRfam9pbih0b3RhbF9maXRlZCwKICAgICAgICAgICAgYnkgPSBjKCJ5ZWFyIiwicmVnaW9uIiwic3BwIikpICU+JQogIG11dGF0ZShwZXJjZW50YWdlID0gc3RhdGVfdmFsdWUvdG90YWxfdmFsdWUqMTAwKSAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUscmVnaW9uLHNwcCkgJT4lIAogIG11dGF0ZShSTWVhbiA9IHpvbzo6cm9sbG1lYW4oeCA9IHBlcmNlbnRhZ2UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgMTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybT1UKQogICAgKSAlPiUgCiAgI09ubHkgc2hvdyByZXN1bHRzIGZvciBzcHJpbmcKICBmaWx0ZXIoc3RyX2RldGVjdChyZWdpb24sIlNwcmluZyIpLAogICAgICAgICAhaXMubmEoUk1lYW4pICMgUmVtb3ZlIE5BcyBmcm9tIHJvbGxtZWFuCiAgICAgICAgICkgJT4lICAKICBsZWZ0X2pvaW4oc3RhdGVfbGF0KQoKIyBQbG90IG1lCnNzcF9hcmVhIDwtIGdncGxvdChzdGF0ZV9maXQpICsKICBnZW9tX2FyZWEoCiAgICBhZXMoCiAgICAgIHggPSB5ZWFyLAogICAgICB5ID0gcm91bmQoUk1lYW4pLAogICAgICBmaWxsID0gb3JkZXIKICAgICAgIyBmaWxsID0gc3RhdGUKICAgICkKICApICsKICB5bGFiKCJQcm9wb3Rpb24gKDEwIHlycyBydW5uaW5nIGF2ZXJhZ2UpIikgKwogICMgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVCwgYWxwaGEgPSAwLjgpICsKICBzY2FsZV9maWxsX21hbnVhbCgKICAgICJTdGF0ZSIsCiAgICB2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQsCiAgICBsYWJlbHMgPSBzdGF0ZV9maXQgJT4lIGFycmFuZ2Uob3JkZXIpICU+JSAgcHVsbChzdGF0ZSkgJT4lIHVuaXF1ZSgpCiAgKSArCiAgbXlfZ2d0aGVtZV9wKGxlZ19wb3MgPSAiYm90dG9tIikgKwogIHRoZW1lKGxlZ2VuZC5rZXkud2lkdGggPSB1bml0KDEsImxpbmUiKSkgKyAKICBmYWNldF93cmFwKH5zcHAsIG5jb2wgPSAxLCBzdHJpcC5wb3NpdGlvbiA9ICJyaWdodCIpCgoKICBnZ3NhdmUoZmlsZW5hbWUgPSAiYXJlYV9wbG90X2F2Z19zcHAuanBnIiwKICAgICAgICAgcGxvdCA9IHNzcF9hcmVhLAogICAgICAgICBwYXRoID0gbXlfcGF0aCgiUiIsIkZpZ3VyZXMiKSwKICAgICAgICAgd2lkdGggPSAxMCwKICAgICAgICAgaGVpZ2h0ID0gMTIKICApCgoKYGBgCiFbUHJvcG9ydGlvbiBjaGFuZ2UgYWdncmVnYXRlZCBhbGwgc3BlY2llcyBtYXAgZm9yIHBhcGVyXSgvVm9sdW1lcy9FbnRlcnByaXNlL0RhdGEvQWNyb3NzQm91bmRhcmllcy9SZXN1bHRzL0ZpZ3VyZXMvYXJlYV9wbG90X2F2Z19zcHAuanBnKQoKIyMgSGlzdG9yaWMgcXVvdGEgVnMgZGlzdHJpYnV0aW9ucwoKVGhpcyBzZWN0aW9uIG9mIHRoZSByZXN1bHRzIGV4cGxvcmVzIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBoaXN0b3JpYyBkaXN0cmlidXRpb24gb2YgdGUgc3RvY2sgYW5kIHRoZSBoaXN0b3JpYyBxdW90YSBhbGxvY2F0aW9uLiBXZSBjb2xsZWN0ZWQgdGhlIHByb3BvcnRpb24gb2YgdGhlIHRvdGFsIHF1b3RhIHRoYXQgZWFjaCBTdGF0ZSBnZXRzIGZvciBlYWNoIHNwZWNpZXMuCgpSaWdodCBub3cgdGhlIGFuYWx5c2lzIG9ubHkgY292ZXJzIGJsYWNrIHNlYSBiYXNzLCBzdW1tZXIgZmxvdW5kZXIgYW5kIHNjdXAuIEJ1dCB3ZSBjYW4gZ28gc3BlY2VpcyBieSBzcGVjaWVzIHRvIHNlZSB3aGljaCBvbmVzIGhhdmUgdGhlaXIgcXVvdGEgYWxsb2NhdGVkIGJ5IHN0YXRlIHRvIGluY2x1ZGUgdGhlbSBpbiB0aGUgYW5hbHlzaXMuCgotIFtCbGFjayBTZWEgQmFzczsgKkNlbnRyb3ByaXN0aXMgc3RyaWF0YSpdKGh0dHBzOi8vd3d3Lm1hZm1jLm9yZy9uZXdzZmVlZC8yMDIxL2FzbWZjLWFuZC1tYWZtYy1hcHByb3ZlLWJzYi1jb21tZXJjaWFsLWFsbG9jYXRpb24tY2hhbmdlcykKCioqTm90ZToqKiBXZSBhcmUgdXNpbmcgdGhlIG5ldyBhbGxvY2F0aW9ucyBiYXNlZCBvbiB0aGUgc3RvY2sncyBtb3N0IHJlY2VudCBiaW9tYXNzIGRpc3RyaWJ1dGlvbiogCgotIFtTdW1tZXIgZmxvdW5kZXJdKGh0dHA6Ly93d3cuYXNtZmMub3JnL3VwbG9hZHMvZmlsZS81ZjlhZjgyYTIwMTlTdW1tZXJGbG91bmRlckZNUF9SZXZpZXcucGRmKQoKLSBbU2N1cF0oaHR0cDovL3d3dy5hc21mYy5vcmcvdXBsb2Fkcy9maWxlLzVmOTlkMDExMjAxOV9TY3VwX0ZNUF9SZXZpZXdfYXBwcm92ZWQucGRmKSBTdW1tZXIgcGVyaW9kCgpGb3IgU3RhdGUtbGV2ZWwgbWFuYWdlZCBzcGVjaWVzIHNlZSB0aGUgW0F0bGFudGljIFN0YXRlcyBNYXJpbmUgRmlzaGVyaWVzIENvbWlzc2lvbl0oaHR0cDovL3d3dy5hc21mYy5vcmcvZmlzaGVyaWVzLW1hbmFnZW1lbnQvcHJvZ3JhbS1vdmVydmlldykgd2Vic2l0ZSBhbmQgZ28gc3BlY2llcy1ieS1zcGVjaWVzLgoKCmBgYHtyIHN0YXRlX3F1b3RhX3RibCxldmFsPSBULCBlY2hvID0gVH0KCnF1b3RhX2FsbG9jYXRpb24gPC0gc3RhdGVfbGF0ICU+JSAKICBtdXRhdGUoCiAgICAiQ2VudHJvcHJpc3RpcyBzdHJpYXRhIiA9IGMoCiAgICAgIDAuMDA0MCwgI01FCiAgICAgIDAuMDA0MCwgI05ICiAgICAgIDAuMTU2NCwgI01BCiAgICAgIDAuMTMyMywgI1JJCiAgICAgIDAuMDM2NywgI0NUCiAgICAgIDAuMDg1NywgI05ZCiAgICAgIDAuMjAxMCwgI05KCiAgICAgIDAuMDQxMSwgI0RFCiAgICAgIDAuMDg4OCwgI01ECiAgICAgIDAuMTYxNCwgI1ZBCiAgICAgIDAuMDg4OCAjTkMKICAgICksCiAgICAiUGFyYWxpY2h0aHlzIGRlbnRhdHVzIiA9IGMoCiAgICAgIDAuMDAwNDc1NiwgI01FIAogICAgICAwLjAwMDAwNDYsICNOSCAKICAgICAgMC4wNjgyMDQ2LCAjTUEgCiAgICAgIDAuMTU2ODI5OCwgI1JJIAogICAgICAwLjAyMjU3MDgsICNDVCAKICAgICAgMC4wNzY0Njk5LCAjTlkgCiAgICAgIDAuMTY3MjQ5OSwgI05KIAogICAgICAwLjAwMDE3NzksICNERSAKICAgICAgMC4wMjAzOTEwLCAjTUQKICAgICAgMC4yMTMxNjc2LCAjVkEKICAgICAgMC4yNzQ0NTg0ICNOQwogICAgKSwKICAgICJTdGVub3RvbXVzIGNocnlzb3BzIiA9IGMoCiAgICAgIDAuMDAxMjEwMSwgI01FCiAgICAgIDAuMDAwMDAwMCwgI0hOCiAgICAgIDAuMjE1ODcyOSwgI01BCiAgICAgIDAuNTYxOTQ1NiwgI1JJCiAgICAgIDAuMDMxNTM5OSwgI0NUCiAgICAgIDAuMTU4MjQ2NiwgI05ZCiAgICAgIDAuMDI5MTY2NywgI05KCiAgICAgIDAuMDAwMDAwMCwgI0RFCiAgICAgIDAuMDAwMTE5MCwgI01ECiAgICAgIDAuMDAxNjUwMiwgI1ZBCiAgICAgIDAuMDAwMjQ5MCAjTkMKICAgICkKICApICU+JSAKICBnYXRoZXIoInNwcCIsInF1b3RhIiw0OjYpCgojIERvdWJsZSBjaGVjayB0aGV5IGFsbCBhZGQgdG8gMS4uLgpxdW90YV9hbGxvY2F0aW9uICU+JSAKICBncm91cF9ieShzcHApICU+JSAKICBzdW1tYXJpc2VfYXQodmFycyhxdW90YSksc3VtKQoKCnF1b3RhX2FsbG9jYXRpb24gJT4lIAogIGFycmFuZ2Uob3JkZXIpICU+JSAKICBzZWxlY3QoLW9yZGVyKSAlPiUgCiAgc3ByZWFkKHNwcCxxdW90YSkgJT4lIAogIGthYmxlKCkKYGBgCgoKIyMjIEdldCBkYXRhIHJlYWR5CgpgYGB7cn0KCnRvdGFsX2ZpdGVkIDwtIGhpc3RvcmljX3NwcCAlPiUgCiAgZ3JvdXBfYnkoeWVhcixyZWdpb24sc3BwKSAlPiUgCiAgc3VtbWFyaXNlKHRvdGFsX3ZhbHVlID0gc3VtKHZhbHVlLG5hLnJtPVQpLC5ncm91cHMgPSAiZHJvcCIpCgojIGdyb3VwIGJ5IHN0YXRlCnN0YXRlX2ZpdCA8LSBoaXN0b3JpY19zcHAgJT4lIAogIGdyb3VwX2J5KHN0YXRlLHllYXIscmVnaW9uLHNwcCkgJT4lIAogIHN1bW1hcmlzZShzdGF0ZV92YWx1ZSA9IHN1bSh2YWx1ZSxuYS5ybT0gVCksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBsZWZ0X2pvaW4odG90YWxfZml0ZWQsCiAgICAgICAgICAgIGJ5ID0gYygieWVhciIsInJlZ2lvbiIsInNwcCIpKSAlPiUKICBtdXRhdGUocGVyY2VudGFnZSA9IHN0YXRlX3ZhbHVlL3RvdGFsX3ZhbHVlKjEwMCkgJT4lIAogICNPbmx5IHNob3cgcmVzdWx0cyBmb3Igc3ByaW5nCiAgZmlsdGVyKHN0cl9kZXRlY3QocmVnaW9uLCJTcHJpbmciKSkKCnF1b3RhX2RmIDwtIHF1b3RhX2FsbG9jYXRpb24gJT4lIAogIGxlZnRfam9pbihoaXN0b3JpY19zcHApICU+JSAKICBncm91cF9ieShzdGF0ZSxhYnJldix5ZWFyLHJlZ2lvbixzcHAscXVvdGEpICU+JSAKICBzdW1tYXJpc2Uoc3RhdGVfdmFsdWUgPSBzdW0odmFsdWUsbmEucm09IFQpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUgCiAgbGVmdF9qb2luKHRvdGFsX2ZpdGVkLAogICAgICAgICAgICBieSA9IGMoInllYXIiLCJyZWdpb24iLCJzcHAiKSkgJT4lCiAgbXV0YXRlKERpc3RyaWJ1dGlvbiA9IHN0YXRlX3ZhbHVlL3RvdGFsX3ZhbHVlKjEwMCwKICAgICAgICAgSGlzdG9yaWMgPSBxdW90YSoxMDApICU+JSAKICBncm91cF9ieShzdGF0ZSxxdW90YSxzcHApICU+JSAKICBtdXRhdGUoUk1lYW4gPSB6b286OnJvbGxtZWFuKHggPSBEaXN0cmlidXRpb24sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgMTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybT1UKQogICAgKSAlPiUgCiAgI09ubHkgc2hvdyByZXN1bHRzIGZvciBzcHJpbmcKICBmaWx0ZXIoc3RyX2RldGVjdChyZWdpb24sIlNwcmluZyIpLAogICAgICAgICAhaXMubmEoUk1lYW4pICMgUmVtb3ZlIE5BcyBmcm9tIHJvbGxtZWFuCiAgICAgICAgICkgJT4lICAKICBsZWZ0X2pvaW4oc3RhdGVfbGF0KSAlPiUgCiAgZmlsdGVyKAogICAgIyBzcHAgPT0iQ2VudHJvcHJpc3RpcyBzdHJpYXRhIgogICAgc3BwICVpbiUgcXVvdGFfYWxsb2NhdGlvbiRzcHAKICApCgpoZWFkKHF1b3RhX2RmKSAlPiUgCiAga2FibGUoKQpgYGAKCiMjIyBFeHBsb3JpbmcgZGlmZmVyZW50IHdheXMgdG8gc2hvdyB0aGUgcmVzdWx0cwoKIyMjIyBEaWZmZXJlbmNlIGxpbmUgcGxvdAoKVGhpcyB2ZXJzaW9uIHNob3dzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIEhpc3RvcmljIHF1b3RhIGFsbG9jYXRpb24gYW5kIHRoZSBkaXN0cmlidXRpb24gcHJvcG9ydGlvbiBvZiB0aGUgc3RvY2s6CgotIGRpZmYgPCAwID0gdGhlIGRpc3RyaWJ1dGlvbiBwcm9wb3J0aW9uIGlzICpsYXJnZXIqIHRoYW4gdGhlIGFsbG9jYXRlZCBxdW90YQotIGRpZmYgPiAwID0gdGhlIGRpc3RyaWJ1dGlvbiBwcm9wb3J0aW9uIGlzICpzbWFsbGVyKiB0aGFuIHRoZSBhbGxvY2F0ZWQgcXVvdGEgCgpgYGB7cn0KIyBPcHRpb24gb25lCgpxdW90YV9kZiAlPiUKICBtdXRhdGUoZGlmZiA9IEhpc3RvcmljLSBEaXN0cmlidXRpb24sCiAgICAgICAgIGRpZmZfcm1lYW4gPSBSTWVhbi0gRGlzdHJpYnV0aW9uKSAlPiUgCiAgZ2F0aGVyKCJ0eXBlIiwidmFsdWUiLGRpZmY6ZGlmZl9ybWVhbikgJT4lIAogICMgVmlldygpCiAgZ2dwbG90KCkgKwogIGdlb21fbGluZSgKICAgIGFlcygKICAgICAgeCA9IHllYXIsCiAgICAgIHkgPSB2YWx1ZSwKICAgICAgY29sb3IgPSBvcmRlcgogICAgKQogICkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCgiU3RhdGUiLAogICAgdmFsdWVzID0gc3RhdGVfcGFsbGV0LAogICAgbGFiZWxzID0gcXVvdGFfZGYgJT4lIGFycmFuZ2Uob3JkZXIpICU+JSAgcHVsbChzdGF0ZSkgJT4lIHVuaXF1ZSgpCiAgICApICsKICBmYWNldF9ncmlkKHR5cGV+c3BwLCAKICAgICAgICAgICAgIHNjYWxlcyA9ICJmcmVlIikgKwogIHRoZW1lX2RhcmsoKQoKYGBgCiMjIyMgTGluZXR5cGUgcGxvdAoKSGVyZSwgd2UgcGxvdCB0aGUgZGlzdHJpYnV0aW9uYWwgcXVvdGEgKHNvbGlkIGxpbmVzKSB3aXRoIGVhY2ggU3RhdGUncyBhbGxvY2F0aW9uIHdpdGggZGFzaGVkICgtLS0tKSBsaW5lcwoKYGBge3J9CiMgT3B0aW9uIG9uZQoKcXVvdGFfZGYgJT4lIAogIGdhdGhlcigibGV2ZWwiLCJxdW90YSIsRGlzdHJpYnV0aW9uOlJNZWFuKSAlPiUgCiAgIyBtdXRhdGUoZGlmZiA9IHF1b3RhX3Blci0gcGVyY2VudGFnZSkgJT4lIAogICMgVmlldygpCiAgZ2dwbG90KCkgKwogIGdlb21fbGluZSgKICAgIGFlcygKICAgICAgeCA9IHllYXIsCiAgICAgIHkgPSBxdW90YSwKICAgICAgY29sb3IgPSBvcmRlcgogICAgKQogICkgKwogIGxhYnMoeCA9ICJZZWFyIix5ID0gIlF1b3RhICglKSIpICsKICBzY2FsZV9maWxsX21hbnVhbCgiU3RhdGUiLAogICAgdmFsdWVzID0gc3RhdGVfcGFsbGV0LAogICAgbGFiZWxzID0gcXVvdGFfZGYgJT4lIGFycmFuZ2Uob3JkZXIpICU+JSAgcHVsbChzdGF0ZSkgJT4lIHVuaXF1ZSgpCiAgICApICsKICBzY2FsZV9jb2xvcl9tYW51YWwoIlN0YXRlIiwKICAgIHZhbHVlcyA9IHN0YXRlX3BhbGxldCwKICAgIGxhYmVscyA9IHF1b3RhX2RmICU+JSBhcnJhbmdlKG9yZGVyKSAlPiUgIHB1bGwoc3RhdGUpICU+JSB1bmlxdWUoKQogICAgKSArCiAgc2NhbGVfbGluZXR5cGUoIlF1b3RhIikgKwogIGZhY2V0X2dyaWQoc3BwIH4gbGV2ZWwpKwogIHRoZW1lX2RhcmsoKQoKYGBgCiMjIyMgRWZmaWNpZW5jeSBpbmRleAoKVGhlIGlkZWEgaGVyZSBpcyBjcmVhdGUgYW5kICplZmZpY2llbmN5IGluZGV4KiAoRGFuZ2VyISkgdGhhdCBjb21wdXRlcyB0aGUgYWxpZ25tZW50IGJldHdlZW4gdGhlIGRpc3RyaWJ1dGlvbiBhbmQgdGhlIGFjdHVhbCBhbGxvY2F0aW9uLiBUaGUgaW5kZXggaXMgc2ltcGx5OwoKJCRlaSA9IFxmcmFje0hpc3RvcmljUXVvdGF9e0Rpc3RyaWJ1dGlvblByb3BvcnRpb259JCQgClNvLCBpbiBjYXNlcyB3aGVyZSAqZWkqID0gMSwgdGhlIHF1b3RhIGlzIGFsaWduZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uOyB3aGVuICplaSogPiAxIHRoZW4gdGhlIGhpc3RvcmljIHF1b3RhIGlzIG1vcmUgdGhhbiB0aGUgc3RvY2sncyBTdGF0ZSdzIGRpc3RyaWJ1dGlvbiwgY29udHJhcmlseSwgKmVpKiA8IDEgbWVhbnMgdGhhdCB0aGUgaGlzdG9yaWMgcXVvdGEgaXMgbGVzcyB0aGFuIHdoYXQgdGhlIFN0YXRlIGN1cnJlbnRseSBoYXMuCgoKKipOb3RlOioqIAotIFRoZXJlIGFyZSBzb21lIGNyYXp6eSBvdXRsaWVycyB0aGF0IGhhdmUgYmVlbiByZW1vdmVkLCBmb3Igbm93Li4uIAotIEJvdHRvbSBwbG90IHJlcHJlc2VudGluZyBpbmRleCBhcyBhIFJtZWFuCgojIyMjIyBBcyBhIG5vcm1hbCB5ZWFyIHRvIHllYXIKCmBgYHtyfQojIE9wdGlvbiBvbmUKCmVmZl9pbmRleCA8LSBxdW90YV9kZiAlPiUgCiAgIyBmaWx0ZXIoCiAgIyAgIHNwcCA9PSJDZW50cm9wcmlzdGlzIHN0cmlhdGEiCiAgIyApICU+JSAKICBtdXRhdGUoaW5kZXggPSBEaXN0cmlidXRpb24vSGlzdG9yaWMsCiAgICAgICAgIGluZGV4X3JtZWFuID0gUk1lYW4vSGlzdG9yaWMpICU+JQogIGdhdGhlcigibGV2ZWwiLCJpbmRleCIsaW5kZXg6aW5kZXhfcm1lYW4pICU+JQogIGZpbHRlcihpbmRleCA8IDUpICMgdGhlcmUgYXJlIHNvbWUgY3JhYWFhenkgb3V0bGllcnMKICAjIFZpZXcoKQogIApnZ3Bsb3QoZWZmX2luZGV4KSArCiAgZ2VvbV9saW5lKAogICAgYWVzKAogICAgICB4ID0geWVhciwKICAgICAgeSA9IGluZGV4LAogICAgICBjb2xvciA9IHN0YXRlCiAgICApLAogICkgKwogIGxhYnMoeCA9ICJZZWFyIix5ID0gIkVmZmljaWVuY3kgaW5kZXgiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwoIlN0YXRlIiwKICAgIHZhbHVlcyA9IHN0YXRlX3BhbGxldCwKICAgIGxhYmVscyA9IHF1b3RhX2RmICU+JSBhcnJhbmdlKG9yZGVyKSAlPiUgIHB1bGwoc3RhdGUpICU+JSB1bmlxdWUoKQogICAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKCJTdGF0ZSIsCiAgICB2YWx1ZXMgPSBzdGF0ZV9wYWxsZXQsCiAgICBsYWJlbHMgPSBxdW90YV9kZiAlPiUgYXJyYW5nZShvcmRlcikgJT4lICBwdWxsKHN0YXRlKSAlPiUgdW5pcXVlKCkKICAgICkgKwogIGZhY2V0X2dyaWQobGV2ZWx+c3BwLAogICAgICAgICAgICAgc2NhbGVzID0gImZyZWUiKSsKICB0aGVtZV9kYXJrKCkKCmBgYAo=